学习《JavaScript设计模式与开发实践》- 单例模式

285 阅读2分钟

概念

单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点,最常见的例子就是一些项目的配置类。

第一次使用类的构造函数时创建一个实例,而后继续调用构造函数的话就只返回这个实例

简单实现

创建一个单例对象类。

    var Singleton = function( name ){
     this.name = name;
     this.instance = null;
    };
    Singleton.prototype.getName = function(){
     alert ( this.name );
    };

保证只有一个对象存在

    Singleton.getInstance = function( name ){
         if ( !this.instance ){
             this.instance = new Singleton( name );
         }
         return this.instance;
    };
    var a = Singleton.getInstance( 'sven1' );
    var b = Singleton.getInstance( 'sven2' );
    alert ( a === b ); // true 

透明的单例模式

我们现在的目标是实现一个“透明”的单例类,用户从这个类中创建对象的时候,可以像使用其他任何普通类一样。在下面的例子中,我们将使用 CreateDiv 单例类,它的作用是负责在页面中创建唯一的 div 节点,代码如下:

var CreateDiv = (function(){
     var instance;
     var CreateDiv = function( html ){
         if ( instance ){
             return instance;
         }
         this.html = html;
         this.init();
         return instance = this;
 };
 CreateDiv.prototype.init = function(){
     var div = document.createElement( 'div' );
         div.innerHTML = this.html;
         document.body.appendChild( div );
     };
     return CreateDiv;
})();
var a = new CreateDiv( 'sven1' );
var b = new CreateDiv( 'sven2' );
alert ( a === b ); // true 

代理实现单例模式

现在我们 把负责管理单例的逻辑移到了代理类 proxySingletonCreateDiv 中。这样一来,CreateDiv 就变成了 一个普通的类,它跟 proxySingletonCreateDiv 组合起来可以达到单例模式的效果。

var CreateDiv = function( html ){
     this.html = html;
     this.init();
};
CreateDiv.prototype.init = function(){
     var div = document.createElement( 'div' );
     div.innerHTML = this.html;
     document.body.appendChild( div );
};
//接下来引入代理类 proxySingletonCreateDiv:
var ProxySingletonCreateDiv = (function(){
     var instance;
     return function( html ){
         if ( !instance ){
             instance = new CreateDiv( html );
         }
         return instance;
     }
})();
var a = new ProxySingletonCreateDiv( 'sven1' );
var b = new ProxySingletonCreateDiv( 'sven2' );
alert ( a === b ); 

惰性单例

惰性单例指的是在需要的时候才创建对象实例.例如网页qq中的登录弹框

由于js是一门无类语音,所以创建实例并不需要那么麻烦,但依然需要注意全局对象容易被污染这一情况

    1. 使用命名空间
    1. 使用闭包封装私有变量

通用惰性单例

所谓通用的惰性单例,实际上就是将管理单例对象和创建单例对象的逻辑分离开来

以创建网页qq登录弹框为例

创建对象逻辑

var getSingle = function( fn ){
     var result;
     return function(){
         return result || ( 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 createSingleLoginLayer = getSingle( createLoginLayer );
    document.getElementById( 'loginBtn' ).onclick = function(){
         var loginLayer = createSingleLoginLayer();
         loginLayer.style.display = 'block';
}; 

最后

本文介绍了JS设计模式中的代理模式的三种情况,如果你觉得本文对你有用的话,不妨点个赞再走呀...