常见的改善前端代码的设计模式-单例模式

前端相对于后端,对于设计模式的理解和主动使用是欠缺的,更多的时候是凭借着经验使用到了,却缺乏对此的理解和认知。

所谓设计模式,就是对一些代码的总结和归纳,使得建立良好的代码有迹可循,知道什么场景怎么去写,这样写有什么样的好处和弊端。

基本概念

定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
使用场景:全局缓存、Windows对象、登录浮窗等
关键:用一个变量来标志是否已经为某个类创建对象,没有则创建,有则返回这个对象

标准单例模式

代码实现:
javascript code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 标准单例模式
* 缺点是使用者必须知道这是个单例类,本来可以直接new xxx,现在变成了xxx.getInstance
*/
var Singleton = function (name) {
this.name = name
this.instance = null
};
Singleton.prototype.getName = function () {
alert(this.name)
}
Singleton.prototype.getInstance = function (name) {
if(this.instance!==null){
this.instance = new Singleton(name)
}
return this.instance
}

透明单例模式

javascript code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 利用闭包和IIFE实现了透明单例模式
* 但违反了单一职责原则
* 缺点是,当不再需要单例时,需要改写构造函数
*/
var CreateDiv = (function() {
var instance
var CreateDiv = function(html) {
if (instance) {
return instance
}
this.html = html
this.init() // 执行init方法
return (instance = this) // 保证只有一个一个对象
}
CreateDiv.prototype.init = function() {
var div = document.createElement('div')
div.innerHTML = this.html
document.body.appendChild(div)
}
return CreateDiv
})()

用代理实现的单例

javascript code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 代理实现单例
* 将负责管理单例的逻辑移到proxySingletonCreate
*/
var CreateSpan = function(html) {
this.html = html
this.init()
}
CreateSpan.prototype.init = function() {
var span = document.createElement('span')
span.innerHTML = this.html
document.body.appendChild(span)
}

var proxySingletonCreate = (function() {
var instance
return function(html) {
if (!instance) [(instance = new CreateSpan('test'))]
return instance
}
})()

创建单例的通用方法

由上可以看出,创建单例的核心即为使用一个变量表示这个对象是否被创建,即:
javascript code

1
2
3
4
var instance
if(!instance) {
instance = xxx
}

具体代码实现即为:
javascript code

1
2
3
4
5
6
7
8
9
10
/**
* 创建单例的抽象方法
* @param {function} fn
*/
var getSingle = function(fn) {
var result
return function() {
return result || (result = fn.apply(this, arguments))
}
}