单例模式
定义: 保证一个类只有一个实例,并提供一个访问它的全局访问点。
var single = function(name){
this.name = name;
this.instance = null;
}
single.prototype.getName = function(){
alert(this.name)
}
single.getInstance = function(name){
if(!this.instance){
this.instance = new single(name)
}
return this.instance
}
var a = new single.getInstance('ffff');
var a2 = new single.getInstance('zzzz');
// a == a2 => true
或者
var single = function(name){
this.name = name;
}
single.prototype.getName = function(){
console.log(this.name)
}
single.getInstance = (function(){
var instance = null;
return function(name){
if(!instance){
instance = new single(name)
}
return isntance
}
})()
使用single类时,我们必须知道它是一个单例类,跟以往new出一个新对象的方式不同,这里要使用single.getInstance来获取对象。
透明的单例
var createDiv = (function(){
var instance = null;
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
})()
这个透明类的单例,我们使用了自执行函数和闭包,并且让这个匿名函数返回真正的single构造方法,增加了代码的复杂度,读起来需要一定的时间来理解
构造函数的作用,实际上做了两件事,创建对象和执行初始化init方法,第二保证了只有一个对象
用代理来实现单例模式
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);
}
引入代理类
var proxySingle = (function(){
var instance;
return function(html){
if(!instance){
instance = new createDiv(html)
}
return instance
}
})()
通过代理模式完成的代码,我把管理单例的逻辑移到了proxySingle里,这样createDiv就变成了一个普通的类
这个例子是缓存代理的应用之一。
惰性单例
惰性单例指的是在需要的时候才创建对象实例。
这种技术在实际开发中非常有用。
在网站首页,有个登陆按钮,点击登录 弹出登录框。很明显这个登录框在页面中是唯一的,不会也不可能出现两个登陆框。
首先我们可以页面加载完成时就加载这个登录框,此时这个登录框出于隐藏状态。
但是如果我进入页面只是想看看,不想进行一些需要登陆的业务操作,此时登陆框的dom节点存在是没有意义的,是一种浪费。
此时,单例模式就更实用了
//dom
<button id="login"></button>
//js
var createLogin = (function(){
var div;
return function(){
if(!div){
div= document.createElement('div');
div.innerHTML = "i'm login form";
div.display.style="none";
document.body.appendChild(div);
return div
}
}
})()
document.getElementById('login').onClick = function(){
var loginDom = createLogin();
loginDom.display.style ='block'
}
通用惰性单例
我们参考上边的代码,如果需要在创建一个iframe单例,或者其他标签,难道需要把上边的函数重新copy一份修改.单例的逻辑可以抽象出来,并且始终不变的,可以理解为
var instance;
if(!instance){
instance = xxx操作
}
return instance
我们将管理单例的逻辑抽象封装起来getInstance
var getInstance = function(fn){
var instance;
return function(){
return instance || (result = fn.apply(this,arguments))
}
}
//创建登陆
var createLogin = getInstance(function(){
var div = document.createElement('div');
div.innerHTML = '我是的登陆';
div.style.display = 'none';
document.body.appenChild(div);
return div
})
//
$('#login').on('click',function(){
var login = createLogin();
$(login).show()
})
//创建script
var createScript = getInstance(function(){
var script = document.createElement('script');
document.appendChild(script)
return script
})
$('#loadScript').on('click',function(){
var script = createScript();
$(script).show();
})
将创建实例对象的职责和管理单例的职责分别放置在两个方法里,这两个方法独立,不会互相影响。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。