单例模式
单例模式「Singleton Pattern」:指一个类只有一个实例,且该类能自行创建这个实例的一种模式,为了节省内存资源、保证数据内容的一致性。

模式动机

在某些系统中,只有一个实例是非常必要的。比如任务管理器,首先从需求上来讲,一个任务管理器窗口完全满足需要。多个任务管理器窗口只会造成额外的开销,还需要处理各个窗口数据同步的问题。

实现

用一个变量来标记当前的类是否创建过对象,如果没创建过,返回创建之后的实例,如果之前已经创建过,则返回之前创建过的实例
单例模式「任务管理器」

代码

1
function TaskManage(name) {
2
this.name
3
}
4
5
TaskManage.getInstance = (function() {
6
let instance = null
7
return function(name) {
8
if (!instance) {
9
instance = new TaskManage(name)
10
}
11
return instance
12
}
13
})()
14
15
// 获取对象1
16
17
const a = TaskManage.getInstance('a')
18
// 获取对象2
19
const b = TaskManage.getInstance('b')
20
// 进行比较
21
console.info(a === b) // true
Copied!
可以看到 ab 是相等的,但是假如我们想让打开的英雄联盟也是单例,我们就必须再写一个英雄联盟的类,并添加 getInstance 方法,这样显然 getInstance 是重复编写的,我们可以将其抽出来单独作为一个类。

通用的单例中间类

首先我们将控制生成单例类的 getInstance 方法抽离出来
1
// 获取单独的实例
2
const singleton = function(fn) {
3
const instance;
4
return function() {
5
return instance || (instance = fn.apply(this, arguments));
6
}
7
}
8
9
// 个人认为这样也可以
10
const singleton = function(Fn) {
11
const instance
12
return function() {
13
return instance || (instance = new Fn(...arguments))
14
}
15
}
16
Copied!
我们再编写一个任务管理器的类
1
const taskManage = function(name){
2
this.name = name
3
}
4
5
taskManage.prototype.getName = function() {
6
return this.name
7
}
Copied!
然后我们将 taskManage 变为单例
1
const TaskManageSingleton = singleton(taskManage)
2
const win = TaskManageSingleton('win')
3
const mac = TaskManageSingleton('mac')
4
5
console.info(win.getName()) // 'win'
6
console.info(mac.getName()) // 'win'
Copied!
可以看到第二次调用 TaskManageSingleton 时传入的参数并未生效,可以得知返回的是之前已经生成的 TaskManage 实例。

小结

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。
Last modified 2yr ago