想必大家都知道单例模式就是不管调用多少次new命令,始终只能创建一个实例对象。
写个方法来看看javaScript的单例长什么样。
下面这个例子是负责在页面中创建唯一的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
})()
是不是跟你写的不太一样,是不是觉得这样写更好?
虽然这已经是优化过的js单例代码,但是他依然有缺点:
为了把instance封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回真正的Singleton构造方法
这增加了一些程序的复杂度,阅读起来比较费劲。
观察这个Singleton构造函数
var CreateDiv = function(html){
if(instance){
return instance;
}
this.html = html;
this.init();
return instance = this;
}
它实际负责了两件事情1:创建对象和执行初始化init方法。2:保证只有一个对象。这与‘单一指责原则’违背
用代理模式实现单一职责的单例
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
}
})()
通过引入代理类的方式实现了单一职责的单例模式。噢耶~~~
CreateDiv只负责创建对象和初始化。ProxySingletonCreateDiv负责保证只有一个对象。
// 创建一个dog单例 来巩固一下
var Dog = function(name){
this.name = name;
this.init();
}
Dog.prototype.init=function(){
console.log('I am dog, my name is '+this.name)
}
var ProxySingletonCreateDog = (function(name){
var instance
return function (name){
if(!instance){
instance = new Dog(name)
}
return instance
}
})()
但是但是!上面的例子更多的接近传统的面向对象的语言实现,而javascript是一门无类语言,生搬单例模式并无意义 呜呜呜。
在javascript中创建单例模式非常的简单,既然我们只需要一个唯一的对象,为什么要为它创建一个类呢???这无异于穿衣服洗澡,传统的单例模式实现在JavaScript中并不适用!!
单例模式的核心1 保证只有一个实例2提供全局访问方法
全局变量不是单例模式,但是我们经常把全局变量当成单例来使用。
全局变量会造成命名空间污染,内存溢出等问题,所以尽量少使用全局变量。
我们可以使用闭包来实现单例
var User = (function(){
var _name = 'stupidcc';
var _age = 18;
return {
getName: function(){
return _name
},
getAge: function () {
return _age
},
setAge: function(age){
_age = age
}
}
})()
惰性单例
惰性是单例模式的重点,重点哦。
这种技术在开发过程中非常有用,有用程度可能超出了你的想象。
例如我们需要在页面中创建一个iframe,使用单例
// 代理
var getSingleton = function(fn){
var result;
return function (fn) {
return result || (result = fn.apply(this,arguments))
}
}
var initIframe = function () {
var iframe = document.createElement('iframe')
document.body.appendChild(iframe)
return iframe
}
var CreateSingletonIframe = getSingleton(initIframe)
document.getElementById('button').onclick=function(){
var iframeObj = CreateSingletonIframe()
}