共计 1283 个字符,预计需要花费 4 分钟才能阅读完成。
单例模式定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式场景:有一些对象往往只需要有一个,比如线程池、全局缓存浏览器中的 Windows 对象等
1、实现单例模式
要实现一个标准的单例模式并不复杂,无非是用一个变量来标志当前是否已经为某个类创建过对象,如果是则在下一次获取该类的实例时,直接返回之前创建的对象
或者:
var Singleton = function(name) {this.name = name;}
Singleton.prototype.getName = function() {console.log(this.name)
}
Singleton.getInstance = (function(name) {
var instance = null
return function(name) {if(!instance) {instance = new Singleton(name)
}
return instance
}
})()
var a = Singleton.getInstance('aa')
var b = Singleton.getInstance('bb')
console.log(a === b) // true
但是这种方法增加了类的“不透明性”,Singleton 必须知道这是一个单例类,且 getInstance 方法是不透明的,使用必须知道又该方法,当我们打印 console.log(new Singleton(‘cc’)),结果如下:
2、透明的单例模式
目的:创建该类时候,可以像使用其他普通类一样;
例子:我们将创建一个 CreateDiv 单例类,它的作用是在页面中创建唯一的 div 节点
这里可以看到当我们 console.log(b)时,构造函数 html 的值还是 ’marin’,到这里我要明确一点 单例模式定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
但是它还是有一些缺点。未了把判断的标志变量 instance 封装起来,我们使用了匿名函数(自运行)和闭包,并让让这个匿名函数返回真正的 Singleton 构造方法,这让阅读起来很难理解,同时增加了程序的复杂程度
var CreateDiv = function(html) {
if(instance) {return instance}
this.html = html;
this.init();
return instance = this
}
这段代码中 CreateDiv 的构造函数实际负责两件事,1、创建实例对象(instance=this)并保证只用一个实例 if(instance)。2、执行初始化 init()。这里还有个缺点(函数的单一职责原则)
假如我们某一天需要用这个类,在页面创建多个 div,即要让这个类从单例类变成一个普通的可以生产多个实例的类,那我们就必须改写 CreateDiv 构造函数,把控制创建唯一的标志变量 var instance 去掉,这种修改会带来不必要的烦恼。
3、用代理来实现单例模式
这样一来就将 CreateDiv 变成一普通类,仅仅去创建 div,
实现单例模式让 ProxySingleton 去实现
单例模式的核心是确保只有一个实例,并提供全局访问