设计模式之单例模式
1. 定义
一个类只有一个实例,并提供一个全局访问点来访问这个实例
2. 口语化举例
单例模式是很常见的设计模式,以至于人们会将全局只有一个且通常只负责一件事的东西叫做单例
比如,一个班级,学生有多个,但是班主任只有一个,这个班级的班主任假设由你来担任,那么,无论何时需要这个班的班主任处理事务,其实都是在找你,这就是只有一个实例
对于班级管理事物,校长不会直接找这个班级,而是找这个班的班主任,而这个班的班主任就是你,所以就找到了你,这就是提供全局访问点
综上,对于一个班级而言,班主任就是一个单例
那,为什么需要单例模式呢?主要原因之一是节省资源,原因之二是全局唯一很多事情更好处理
可以这样理解:一个班假如有多个班主任,会需要更多的教师资源,并且,不同班主任之间处理事情不一样会导致分歧,管理困难
(下面的描述会沿用这个上述这个场景)
3. 源码示例
单例模式在前端很常见,前端工程中很多代码对象都需要使用单例,比如工具类、网络请求类等
这些代码对象在多处都会使用到,且功能都很通用,所以没必要多次创建、销毁,只需要全局创建一个对象即可
严格意义上来讲,单例模式需要满足构造函数私有化,外部只能通过静态函数获取实例
但是前端广泛使用的单例模式通常是广义上的,类似于全局变量形式的单例模式,比如Vuex
Vuex 是 Vue.js 的官方状态管理库,它使用单例模式来管理应用的全局状态。Vuex 的 store 对象是一个单例,它保存了应用的状态,并提供了一些方法来更新和获取状态,所以你可以在Vue项目中随时调用Vuex 的 store 对象
在项目初始时,创建Store,通常带有唯一标识的Key:
function createStore (options) {
return new Store(options)
}
function install (app, injectKey) {
// 借助Vue来实现全局注入
app.provide(injectKey || storeKey, this)
app.config.globalProperties.$store = this
// ...
}
在使用时,通常只需要useStore即可:
function useStore (key = null) {
// 借助Vue来实现全局获取
return inject(key !== null ? key : storeKey)
}
4. 总结
4.1 设计原则
-
保证一个类只有一个实例
一个班级只有一个班主任
-
仅在首次请求单例对象时对其进行初始化
一个班级建立之初设置好班主任,之后这个班级的班主任通常不再改变
-
获得了一个指向该实例的全局访问节点
这个班级的事找当班主任的这个人
-
在多线程环境下需要进行特殊处理
班级事情多且同时发生时,班主任一个人必须要处理
4.2 适用场景
- 某个类对于所有客户端只有一个可用的实例
- 更加严格地控制全局变量,可以使用单例模式
5. 参考资料
[1] 单例设计模式 (refactoringguru.cn)
[2] vuejs/vuex: 🗃️ Centralized State Management for Vue.js. (github.com)

浙公网安备 33010602011771号