设计模式之单例模式
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点!
例如 有些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的window对象、jq对象等。我们在登录的时候登录的浮窗,无论我们点了多少次登录 浮窗只会被创建一次 这个浮窗我们就可以用单列模式来创建。
1.简单实现下单例模式
思路:用一个类创建对象,如果下次再次使用该类的实例对象的时候,直接返回之前的对象,,要通过一个变量来记录是否为某类创建过对象
var a=function(name){
this.name=name
this.instance=null
};
a.prototype.getName = function(){
alert(this.name)
}
a.getInstance = function(name){
if(!this.instance){
this.instance = new a(name)
}
return this.instance
}
var b = a.getInstance('zhangsan')
var c = a.getInstance('lisi')
alert(b=== c) //? true
2.‘透明’的单例模式
目标:实现一个‘透明’的单例类。从这个类中创建对象的时候,可以像使用其他任何普通类一样
需求:在页面上中创建卫衣的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('zhangsan')
var b = new CreateDiv('lisi')
elert(a===b) //? true
简单实现了上面的需求跟目标,看代码能发现一些缺点
//现在的Singleton构造函数
var CreateDiv = function(html){
if(instance){
return instance
}
this.html = html
this.init()
return instance = this
}
为了把instance封装起来,我们使用了自执行函数的匿名函数和闭包 并且让这个匿名函数返回真正的Singleton构造函数, 在一定程度上增加了 程序的复杂程度 不易阅读
CreateDiv 的构造函数主要负责了两件事 1、创建对象和执行初始化函数 2.保证只有一个对象实例。假如 有一天我们利用这个类创建千千万万个DIV,即要让这个类 从单例类 变成 一个普通的 可以创建多个实例的类,那我们必须要改写CreateDiv 构造函数,去掉控制创建唯一对象的那一层去掉,这种修改也会给我们带来别的麻烦。
3.用代理实现单例模式
引入代理类的概念,主要是解决上面提到的问题。
通过2后面提出的问题 对CreateDiv 构造函数进行改造 把单例的代码移除 是它成为一个普通的创建DIV的类;
var CreateDiv = function(html){
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)
}
接着引入代理类 PrototypeCreateDiv
var PrototypeCreateDiv = (function(){
var instance;
return function( html ){
if( !instance ) {
instance = new CreateDiv( html );
}
return instance
}
})();
var a = new PrototypeCreateDiv('zhangsan')
var b = new PrototypeCreateDiv('lisi')
alert(a===b) //? true
引入代理类的方式 ,我们同样也完成了一个单例模式的编写,跟之前不同的是 现在我们把负责管理单例的逻辑 移到了 代理类 PrototypeCreateDiv 中。CreateDiv的也变成了一个普通的类,它与PrototypeCreateDiv 组合起来 达到单例模式的效果!(这个也是缓存代理的应用之一)
参考文献 :JavaScript设计模式与开发实践