Skip to content

单例模式

什么是单例模式

意图

保证一个类仅有一个实例,并提供一个访问它的全局访问点。避免了一个全局使用的类频繁地创建与销毁。

模式特点

  • 类只有一个实例
  • 全局可访问该实例
  • 自行实例化
  • 可推迟实例化(即在需要用到的时候)

最简单的实现

js
function Person (name) {
  this.name = name;
}
let single = (function getSingleObj() {
  let instance = null;
  return function() {
      if(!instance) {
          instance = new Person('张三');
      }
      return instance;
  }
})()
let a = single();
let b = single();
console.log(a === b) // true

如果你懂的闭包原理的话,那么就很明显能看出,单例模式就是使用了闭包。 用闭包保存了instance,致使你每次调用single函数都是访问的同一个instance。

使用类的静态实现

js
function Person (name) {
    this.name = name;
}
class Single {
    static getObj() {
        if(!Single.instance) {
            Single.instance = new Person('张三');
        }
        return Single.instance;
    }
}
let a = Single.getObj();
let b = Single.getObj();
console.log(a == b);

使用类的静态来实现,其实就是在类的原型上挂载了一个instance属性,每次访问的都是从类(构造函数)原型上访问instance属性。

个人觉得使用类的静态来实现,代码更加简洁直观。

应用场景

Vuex

我们在 Vue 里面安装 Vuex 时,其实就是使用了单例模式的思维来安装 Vuex。

js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

Vue 的use函数其实就是调用 Vuex 里面的Install函数

js
// Vuex
export function install (_Vue) {
  // 判断Vue是否已经 install Vuex
  if (Vue && _Vue === Vue) { 
    if (__DEV__) {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  Vue = _Vue    // 若没有,那么则为这个 Vue 实例对象 install Vuex
  applyMixin(Vue)
}