什么叫单例模式,保证一个类仅有一个实例,提供一个全局的访问点,这就叫做单例模式
我们先不考虑他是如何实现的,我们先来思考一个问题,如何保证一个类仅有一个实例?一般情况下,当我们创建了一个类(本质是构造函数),可以通过new关键字用构造函数构造任意多个实例对象比如
class SingDog{
show(){
console.log('我是一个单例对象')
}
}
const s1 = new SingleDog()
const s2 = new SingleDog()
// false
s1 === s2
很明显我们开辟了两个内存对象去实例化一个构造函数,这两个实例的对象是互相没有任何关系的。
那么我们来思考一下要具备上述条件就要构造函数能够检测自己是否已经被实例化的能力,我们现在把这个逻辑写成一个静态方法(也可以写入静态函数的函数体内)
class singleDog{
show(){
console.log('我是一个单例对象')
}
static getInstance(){
// 判断是否已经new过一个实例
if(!singleDog.instance){
// 如果这个实例不存在
singleDog.instance = new singleDog()
}
// 如果存在就直接返回
return SingleDog.instance
}
}
const s1 = singleDog.getInstance()
const s2 = singleDog.getInstance()
s1 == s2 // true
除了用上述的逻辑实现已外还可以用闭包的方式来实现
SingleDog.getInstance = (function(){
let instance = null
return function(){
if(!instance){
instance = new SingDog()
}
return instance
}
})()
可以看出,在getInstance方法的判断和拦截下,我们不管调用多少次,SingleDog都只会给我们返回一个实例,s1和s2现在都指向这个唯一的实例。
单例模式在Vuex中的运用
先想象一下Vuex是怎么实现只能注册一次的呢
Vuex如何确保Store的唯一性,我们先来看看怎么在项目中引入Vuex
// 安装Vuex
Vue.use(Vuex)
// 将store注册到Vue实例中
new Vue({
el:'#app',
store
})
通过调用Vue.use(),我们安装了Vuex。Vuex是一个对象,它在内部实现了一个install方法,这个方法会在插件安装的时候被调用,从而把Store注册到Vue实例里面去。也就是每install一次,都会尝试给 Vue 实例注入一个 Store。
小结
大家想象一一下要是没有单例模式会发生什么事情,会带来什么养样的麻烦, 我们通过上面的源码解析可以看出假如install里没有单例模式的逻辑,那我们如果在一个应用里不小心多次安装了插件:
/ 在主文件里安装Vuex
Vue.use(Vuex)
...(中间添加/修改了一些store的数据)
// 在后续的逻辑里不小心又安装了一次
Vue.use(Vuex)
失去了单例判断能力的 install 方法,会为当前的Vue实例重新注入一个新的 Store,也就是说你中间的那些数据操作全都没了,一切归 0。因此,单例模式在此处是非常必要的。
除了说在 Vuex 中大展身手,我们在 Redux、jQuery 等许多优秀的前端库里也都能看到单例模式的身影