单例模式

单例模式

@(记录)[读书笔记]

单例模式:保证一个类中仅有一个实例,并提供一个访问它的全局访问点。

有一些对象我们往往只需要一个,比如线程池,全局缓存,浏览器的window对象等等,在JavaScript开发中,单例模式应用十分广泛。当我们点击登录按钮的时候,页面出现一个登录的浮窗,而这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗适合用单例模式来创建。

实现起来就是使用一个变量标记当前是否已经为类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//简单单例模式
var Singleton = function(name) {
this.name = name;
this.instance = null;
};
Singleton.prototype.getName = function() {
console.log(this.name);
};
Singleton.getInstance = function(name) {
if (!this.instance) { //如果没有创建过,则new一个实例
this.instance = new Singleton(name);
}
return this.instance; //否则返回已经存在的实例
};
var a = Singleton.getInstance('mewhat1');
var b = Singleton.getInstance('mewhat2');
console.log(a === b);//true

通过Singleton.getInstance获取Singleton类的唯一对象。和Java实现的单例模式一样,通常是通过在类中实现getInstance方法来设置唯一的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//或者
var Singleton = function(name) {
this.name = name;
};
Singleton.prototype.getName = function() {
console.log(this.name);
};
Singleton.getInstance = (function() {
var instance = null;
return function(name) {
if (!instance) {
instance = new Singleton(name);
}
return instance;
}
})();
var a = Singleton.getInstance('mewhat1');
var b = Singleton.getInstance('mewhat2');
console.log(a === b);//true

透明的单例模式:用户从类中创建对象的时候,可以像使用其他任何普通类一样(使用new创建)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var CreateDiv = (function() {
var instance;
//CreateDiv的构造函数,创建对象和执行初始化的init(写法别扭)
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('sven1');
var b = new CreateDiv('sven2');
console.log(a === b);//true

用代理实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 ProxySingletonCreateDiv = (function() {
var instance;
return function(html) {
if (!instance) {
instance = new CreateDiv(html);
}
return instance;
}
})();
var a = ProxySingletonCreateDiv('sven1');
var b = ProxySingletonCreateDiv('sven2');
console.log(a === b);//true

惰性单例模式:在需要的时候才创建对象实例,在调用getInstance方法的时候才创建对象或者如果对象已经存在的话,直接返回对象;
设计模式中考虑的原则有很多,基本的是:单一原则,最少知识原则,开放-封闭原则……
下面单例违反了单一原则,单一是说每一个函数或者对象的职责是独立单一的不合其他职责混合
创建对象和管理单例的逻辑都放在createLoginLayer对象内部了,违反了单一原则。

1
2
3
4
5
6
7
8
9
var createLoginLayer = (unction(name) {
var instance = null;
return function(name) {
if (!this.instance) { //如果没有创建过,则new一个实例
instance = new Singleton(name);
}
}
return instance; //否则返回已经存在的实例
})();

通用的惰性单例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var getSingle = function(fn) {
var result;
return function() {
//将fn函数动态添加到getSingle函数内
return result || (result = fn.apply(this,arguments));
}
};
var createLoginLayer = function() {
var div = document.createElement('div');
div.innerHTML = "Login";
div.style.display = 'none';
document.body.appendChild(div);
return div;
};
//test
var createSingle = getSingle(createLoginLayer);
document.getElementById('login').onclick = function() {
var loginLayer = createLoginLayer();
loginLayer.style.display = 'block';
}
坚持原创技术分享,您的支持将鼓励我继续创作!