单例模式
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
1、实现单例模式
实现单例模式并不难,无非就是使用一个变量来标志当前是否已经为某个类创建过实例,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。代码如下所示:
var Singleton = function (name) {
this.name = name
}
Singleton.prototype.getName = function () {
console.log(this.name)
}
Singleton.getInstance = (function () {
let instance = null
return function (name) {
if (!instance) {
instance = new Singleton(name)
}
return instance
}
})()
可以通过下面的测试代码测试是否只有一个实例:
var a = Singleton.getInstance('tom')
var b = Singleton.getInstance('jack')
console.log(a === b) // true
- 虽然上面通过
Singleton.getInstance
来获取Singleton
类的唯一对象,实现了单例模式的编写,但这段单例模式代码的意义不大。 - 增加了这个类的“不透明性”,Singleton 使用者必须知道这是一个单例类,跟以往通过
new XXX
的方式获取对象不同,偏要使用Singleton.getInstance
来获取对象。 - 还是能通过
new XXX
方式来获取对象。
2、透明的单例模式
现在我们的目标是实现一个“透明”的单例类,用户从这个类创建对象时,可以像使用其他任何普通类一样 new XXX
。代码如下:
var Singleton = (function () {
var instance = null
var Singleton = function (name) {
if (instance) {
return instance
}
this.name = name
return (instance = this)
}
return Singleton
})()
var a = new Singleton('hh')
var b = new Singleton('kk')
console.log(a === b) // true
这段代码中,Singleton
的构造函数实际上负责了两件事情:
- 创建对象
- 保证只有一个对象
现在有个问题,某天需要这个类创建多个实例,那么不得不把控制创建唯一对象的那一段去掉,这种修改会很麻烦,下面使用代理的方式来解决这个问题
3、用代理实现单例模式
先看代码:
var Singleton = function (name) {
this.name = name
}
Singleton.prototype.getName = function () {
console.log(this.name)
}
var proxySingleton = (function () {
var instance = null
return function (name) {
if (!instance) {
instance = new Singleton(name)
}
return instance
}
})()
var a = new proxySingleton('hh')
var b = new proxySingleton('kk')
console.log(a === b)
上面引入了代理类来实现单例模式,与之前不同的是,把负责管理单例的逻辑移到了代理类 ProxySingleton
中,Singleton
就变成了一个普通类
这个也是缓存代理的应用之一
4、惰性单例
惰性单例指的是在需要的时候才创建对象实例。惰性单例是单例模式的重点,这种技术非常有用,开头的例子就使用这种技术,instance
实例对象总是在调用 Singleton.getInstance
的时候才被创建
5、面试题目
5.1、实现一个 Storage
- 描述:
- 思路:
碰到单例模式的题目,首先要知道 getInstance
和 instance
是干嘛用的,然后实现上,把判断逻辑写入静态方法或者构造函数里都没关系
- 实现:
class Storage {
static getInstance() {
if (!Storage.instance) {
Storage.instance = new Storage()
}
return Storage.instance
}
getItem(key) {
return localStorage.getItem(key)
}
setItem(key, value) {
return localStorage.setItem(key, value)
}
}
const storage1 = Storage.getInstance()
const storage2 = Storage.getInstance()
storage1.setItem('name', '李雷')
// 李雷
storage1.getItem('name')
// 也是李雷
storage2.getItem('name')
// 返回true
storage1 === storage2
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!