设计模式之1单例模式

2018-04-18  本文已影响0人  钱学敏

把技术还原为生活。

定义

保证一个类只能有一个实例,并提供一个访问它的全局访问点,如window对象。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>设计模式之单例模式</title>
</head>

<body>
    <pre>单例模式</pre>
    <button id="loginBtn">弹出窗口</button>
    <script>
    //--------------1 透明的单例

    var CreateDiv = (function() {
        var instance; //用一个变量标识是否已经创建过对象
        var CreateDiv = function(html) {
            if (instance) { //如果已经创建
                return instance; //直接返回
            }
            this.html = html;
            this.init();
            instance = this;
            return instance;
        }

        CreateDiv.prototype.init = function() {
            var div = document.createElement('div');
            div.innerHTML = this.html;
            document.body.appendChild(div)
        }
        return CreateDiv;
    })()

    var a = new CreateDiv('a') //只实例化一次
    var b = new CreateDiv('b')
    alert(a == b) //true

    /**
     *上述方式的缺陷是 如果有一天需要创建很多个对象,而不只是一个,
     *即要让这个类从单例变成一个普通的可产生多个实例的类,
     *就需要修改 CreateDiv 构造函数 不符合“单一职责原则”
     *可以用代理实现单例模式解决这个问题
     */

    //--------------2 用代理实现单例模式

    var CreateDiv = function(html) { //一个普通的创建div的类
        this.html = html;
        this.init();
    }

    CreateDiv.prototype.init = function() {
        var div = document.createElement('div');
        div.innerHTML = this.html;
        document.body.appendChild(div)
    }

    var proxySingletonCreateDiv = (function() { //代理类 与普通类 组合实现单例模式
        var instance;
        return function(html) {
            if (!instance) {
                instance = new CreateDiv(html);
            }
            return instance;
        }
    })()

    var a = new proxySingletonCreateDiv('a');
    var b = new proxySingletonCreateDiv('b');
    alert(a === b)

    //---------------3 简化版单例模式
    //1、 使用命名空间
    var nameSpace = {
        init: function(argument) {
            var me = this;
            me.render();
            me.bind();
        },
        render: function(argument) {
            var me = this;
            console.log('render')
        },
        bind: function(argument) {
            var me = this;
            console.log('bind')
        }
    }

    nameSpace.init();

    // 2使用闭包封装私有变量
    var user = (function() {
        var __name = 'sevn',
            __age = 25;

        return {
            getUserInfo: function() {
                return __name + '-' + __age;
            }
        }
    })()
    alert(user.getUserInfo())


    //----------4 通用的惰性单例   创建弹窗
    //管理单例的职责
    var getSingle = function(fn) {
        var result;
        return function() {
            return result || (result = fn.apply(this, arguments))
        }
    }

    //创建实例对象的职责 具体的业务逻辑
    var creatLoginLayer = function() {
        var div = document.createElement('div');
        div.innerHTML = '我是登录弹出窗口';
        div.style.display = 'none';
        document.body.appendChild(div);
        return div;
    }

    // 创建实例对象的职责和管理单例的职责一起完成唯一实例对象的创建
    var createSingleLoginLayer = getSingle(creatLoginLayer);

    document.getElementById('loginBtn').onclick = function() {
        var loginLayer = createSingleLoginLayer();
        loginLayer.style.display = 'block'
    }
    </script>
</body>

</html>
上一篇 下一篇

猜你喜欢

热点阅读