JavaScript设计模式与开发实践 单例模式

  单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  当我们点击登陆按钮时,页面会出现登陆浮窗,无论点击多少次按钮,这个浮窗只会被创建一次,那么它就适合用单例模式来创建。

1 JavaScript中的单例模式

  我们经常把全局变量当成单例模式使用,但它会造成命名空间污染。可以用以下方法降低全局变量带来的命名污染。

  1 .1使用命名空间

  最简单的方法是用字面对象量:

var namespace = {
    a: function{
        alert(1);  
    },
    b: function{
        alert(1);  
    }
}

  还可以动态创建命名空间:

var MyApp = {};

MyApp.namespace = function( name ) {
    var part = name.split('.');
    var current = MyApp;
    for(var i in part) {
         if(! current[ part[ i ] ]) {
             current[part[ i ]] = {};
         }
         current = current[ part[ i ] ]
    }
}

MyApp.namespace( 'event' );

MyApp.namespace( 'dom.style' );


//上述代码等于

var MyApp = {
    event: {},
    dom: {
        style: {}
    }
}

  1 .2使用闭包封装私有变量

  把变量来封装在闭包内,只暴露一些接口与外界通信:  

var user = (function() {
    var _name = 'sun',
         _age = 9;
   return {
       getUserInfo: function() {
           return _name = '-' + _age
       }
   }
})()

2 惰性单例

  惰性单例是指在需要时才创建对象实例。

  这是一个可用的惰性单例,但它违反单一职责原则,创建对象和管理单例的逻辑都放在createLoginLayer中。要创建其他标签时,还要把函数几乎重写一次。  

    var createLoginLayer = (function(){
        var div;
        return function(){
            if ( !div ){
                div = document.createElement( 'div' );
                div.innerHTML = '我是登录浮窗';
                div.style.display = 'none';
                document.body.appendChild( div );
            }
            return div;
        }
    })();

    document.getElementById( 'loginBtn' ).onclick = function(){
        var loginLayer = createLoginLayer();
        loginLayer.style.display = 'block';
    };

  把管理单例的逻辑抽出,封装在函数内部,创建对象的方法fn作为参数动态传入。

  将用来创建浮窗的方法以fn参数传入getSingle,让getSingle返回一个新函数,并用result保存fn的结果,result因为保存在闭包不会被销毁。如果result已经被赋值,返回这个值。

var getSingle = function( fn ) {
    var result;
    return function(){
        return result || fn.apply(this, arguments);
    }
}
    var createLoginLayer = function(){
        var div = document.createElement( 'div' );
        div.innerHTML = '我是登录浮窗';
        div.style.display = 'none';
        document.body.appendChild( div );
        return div;
    };

    var createSingleLoginLayver = getSingle( createLoginLayer );

    document.getElementById( 'loginBtn' ).onclick = function(){
        var loginLayer = createSingleLoginLayer();
        loginLayer.style.display = 'block';
    };
原文地址:https://www.cnblogs.com/surahe/p/6026959.html