javaScript是一种弱类型、动态的、基于原型的语言,这种语言特性使得它非常容易、
甚至是普通的方式实现其中的一些模式。
单体模式的思想在于保证一个特定类仅有一个实例。这就意味着当您第二次使用同一个
类创建新对象的时候,应该得到与第一次所创建对象完全相同对象。
在javaScript中没有类,只有对象。当您创建一个新对象时,实际上没有其他对象与其
类似,因此新对象已经是单体了。使用对象字面量创建一个简单的对象也是一个单体的
例子。
var obj ={
myprop:’my value’
};
在javaScript中,对象之间永远不会完全相等,除非他们是同一个对象,因此即使创建
一个具有完全相同成员的同类对象,它也不会与第一个对象完全相同。
var obj2 = {
myprop:’mu value’
};
obj === obj2 //false
obj == obj2 //false
因此,可以认为每次在使用对象字面量创建对象的时候,实际上就正在创建一个单体,
并且并不涉及任何特殊语法。
javaScript中并没有类,因此对单体咬文嚼字的定义严格说来并没有意义。但是
javaScript中具有new语法可使用构造函数来创建对象,而且有时可能需要使用这种语法
的单体实现。这种思想在于当使用一个构造函数以new操作符来创建多个对象时,应该仅
获得指向完全相同的对象的新指针。
下面的代码显示了其预期行为
var uni = new Universe();
var uni2 = new Universe();
uni === uni2; //true
在上面的例子中,uni对象仅在第一次调用构造函数时被创建。在第二次及以后的创建时
将会返回同一个uni对象。这就是为什么uni===uni2,因为它们本质上是指向同一个对象
的两个引用。那么如何在javaScript中实现这种模式呢?
需要Universe构造函数缓存该对象实例this,以便当第二次调用该构造函数时能够创建并
返回同一个对象。有多种选择可以实现这一目标:
1.可以使用全局变量来存储该实例,但是并不推荐使用这种方法,因为在一般原则下,
全局变量有部分缺点。此外,任何人都能覆盖该全局变量。
- 可以在构造函数的静态属性中缓存该实例,javaScript中的函数也是对象,因此它们
也可以有属性。可以使用类似Universe.instance的属性并将实例缓存在该属性重工,这
是一种很好的实现方法,这种解决方案唯一的缺点在于instance属性是公开可访问的属
性,在外部代码中可能会修改该属性,以至于会丢失了该实例。
如例子:
function Universe(){
//判断是否有实例
if(typeof Universe.instance === ‘object’){
return Universe.instance;
}
//正常进行
this.start_time = 0;
this.bang = “Big”;
//缓存
Universe.instance = this;
}
//
var uni = new Universe();
var uni2 = new Universe();
uni === uni2; //true
这种方法是一个非常直接的解决方法,其唯一的缺点在于其instance属性是公开的,虽
然其他代码不太可能会无意中修改该属性,但是仍然存在这种可能性。
3.可以将该实例包装在闭包中。这样可以保证该实例的私有属性并且保证该实例不会被
构造函数之外的代码所修改,缺点就是带来了额外的闭包开销。
如下面例子:
function Universe(){
//缓存实例
var instance = this;
//正常进行
this.start_time=0;
this.bang = “big”;
//重写该构造函数
Universe = function(){
return instance;
};
}
var uni = new Universe();
var uni2 = new Universe();
uni === uni2; //true
当第一次调用原始构造函数时,它像往常一样返回this,然后,在第二次、第三次调用
时,将执行重写构造函数。该重写构造函数通过闭包访问了私有instance 变量,并且仅
简单返回了该instance.在重写构造函数会丢失所有在初始定义和重定义时刻之间添加到
它里面的属性。在这列的特定情况下,任何添加到universe的原型中对象都不会存在指
向由原始实现所创建实例的活动链接。
另外一种方法是将构造函数和实例包装在即时函数中。在第一次调用构造函数时,它会
创建一个对象,并且似的私有instance指向该对象,从第二次调用之后,该构造函数仅
返回该私有变量,通过这个新的实现方式,前面所有代码片段的测试也都会按照预期运
行。
var Universe;
(function (){
var instance;
Universe = function Unvierse(){
if(instance){
return instance;
}
instance = this;
//所有功能
this.start_time = 0;
this.bang = “Big”;
};
}());