单例模式是所有设计模式中最简单易懂的设计模式之一,故很多人都会以单例模式作为学习设计模式的第一站,很多很多教学网站或会以单例作为教学的第一章。Let's enjoy :P.
特点
- 使用单例的类,有且仅有一个实例对象。
- 使用单例的类的实例对象由该类自行创建。
- 单例类需提供一个对外的访问接口供外部调用方进行调用,可以通过该类访问到该类的实例对象。
适用场景
1.需要频繁创建的类,使用单例可以降低系统内存压力。 2. 某些具有唯一性的类,比如接口模块的集合,一个系统有且仅有一个相同模块的接口集合。从逻辑上而言,使用单例应该是单一控制的类或者方法。 3. 当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。
Good & Bad
Good
- 使用单例可以来降低内存压力,减少内存开销。
- 单例模式可以全局共享一个实例,可以避免对资源的浪费,优化资源的访问。
Bad
- 单例模式通常都将功能代码写于同一个类中,如果业务逻辑设计不合理,拓展起来比较困难,都需要修改其原本的实体对象,违背了开闭原则。
- 在并发的场景下,由于全局共享一个实例对象,调试困难。
How
- 构造函数私有化,确保用户无法通过
new来进行实例化。
类型
可分为饿汉型和懒汉型两种,主要区别在于创建实例对象的时机不同。
饿汉型
创建类时就生成好了实例对象。
class Singleton {
private static instance: Singleton = new Singleton()
private constructor() {}
// 饿汉模式
public static getInstance(): Singleton {
return Singleton.instance
}
}
懒汉型
只有在第一次被调用时,才初始化实例对象
class Singleton {
private static instance: Singleton
private constructor() {}
public static getInstance(): Singleton {
// 懒汉模式
if (!Singleton.instance) {
Singleton.instance = new Singleton()
}
return Singleton.instance
}
}
Extension 拓展形态
随机有限多实例
创建有限个实例,并将每个实例对象保存于类中的 list。在调用方进行调用时,在实例 list 中返回其中一个供调用方使用。
- 随机: 实际上这个返回策略可以自己决定
- 有限: 主要是指在类里面规定好了实例个数,不因运行时其他状态而改变。
class Multiton{
private constructor(message:number){
this.message = message + ''
}
private static instanceList: Multiton[] = []
public static getInstance() : Multiton{
if(!this.instanceList.length){
// 创建单例类之初就已经规定好了实例个数
for(let i = 0;i<5;i++){
this.instanceList.push(new Multiton(i))
}
}
if(this.instanceList.length){
// 返回的策略可以根据实际需求进行调整
const randomIdx = Math.floor(Math.random() * 5)
return this.instanceList[randomIdx]
}
}
public message:string
public hello(){
console.log(this.message)
}
}
const a1 = Multiton.getInstance()
const a2 = Multiton.getInstance()
const a3 = Multiton.getInstance()
a1?.hello()
a2?.hello()
a3?.hello()
For more information: