设计模式:单例模式

单例模式(The Singleton Pattern)

单例模式的特征是限制创建的类的实例为一个单独的对象, 比较典型的例子是: 如果实例不存在, 那么通过方法创建类的实例, 否则, 返回这个实例, 单例模式的实例仅有一个, 因此被称作单例模式;例如下面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let singleton = (function () {
let instance;
function init() {
return {
publicName: name,
}
}
return {
getInstance: function() {
if (instance === undefined) {
instance = init();
}
return instance;
}
}

})();
当我们引用上面的实例时, 我们始终引用到的是一个实例:
1
singleton.getInstance() === singleton.getInstance() // true
使用单例模式有什么好处呢?
  1. 当当前页面需要一个公共的对象或者全局缓存的时候, 我们需要使用单例模式, 实现例如全局变量存储,线程池之类的功能, 使用单例可以让多个引用的实例状态保持一致, 因此这些多次引用只是引用的同一个实例
  2. 划分命名空间, 避免全局变量污染
  3. 在使用的时候实例化对象, 可以防止如果引入大的资源的时候出现较大的内存占用, 特别当创建实例的 cost 较大的时候
我们可以使用单例模式的情况:
  • There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
  • When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.
  • 对于一个类而言, 必须有只有一个确定的实例, 而且对于使用者来说, 这个实例可以通过一个很明确的地方获取到, 比如上面的 getInstance 方法
  • 通过添加子类, 这个唯一的实例应该能够是可扩展的, 使用者应该在不改变原来代码的情况下是使用扩展的实例, 例如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    getInstance: function() {
    if (instance === undefined) {
    // 通过 if 的方式切换应用的类
    if (useClassA) {
    instance = new classA();
    } else {
    instance = init();
    }
    }
    return instance;
    }