# 单例模式
# 参考
- https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/singleton.html (opens new window)。
- https://refactoringguru.cn/design-patterns/singleton (opens new window)。
# 定义
确保一个类仅有一个实例,并为该实例提供一个全局访问点。
# 应用场景
程序中某个类需要保证只存在一个可用的实例,如浏览器 window
对象,应用中的 toast
,dialog
组件等等。
# 实现思路
在类或者函数中添加一个变量用于保存单例实例。
声明一个方法专门用于获取该单例实例。
获取实例的方法中,首次调用会创建该实例并且保存到一个变量之中,之后每次调用都返回该实例。
# 优点
实现了全局唯一实例,共享的概念。
实例永远只有一个,比较节省内存。
# 缺点
- 违背了“单一职责原则”,单例类既充当产品,作为产品类本身,又充当工厂,提供获取实例的方法。
# 代码实例
// 实现方式1: 使用高阶函数缓存实例˝
const getSingle = (fn: Function) => {
let singleton
return function() {
return singleton || (singleton = fn.apply(this, arguments))
}
}
class Person {
name: string
constructor(name: string) {
this.name = name
console.log('only log once.')
}
setName(name: string) {
this.name = name
}
}
const getPerson = getSingle(() => new Person('xuwenchao'))
const p1 = getPerson()
const p2 = getPerson()
p2.setName('xuwenchao2')
console.log(p1, p2, p1 === p2)
// 实现方式2: 由类提供获取实例的静态方法
class Dialog {
instance: Dialog
static instance: Dialog
// 使用 private,防止外部使用 new 进行实例化
private constructor() {
this.instance = null
}
// 获取单例实例的静态方法
static getInstance(): Dialog {
if (this.instance) return this.instance
return (this.instance = new Dialog())
}
}
const dialog1 = Dialog.getInstance()
const dialog2 = Dialog.getInstance()
console.log(dialog1 === dialog2)