设计模式 | 单例模式

498 阅读3分钟

单例模式是所有设计模式中最简单易懂的设计模式之一,故很多人都会以单例模式作为学习设计模式的第一站,很多很多教学网站或会以单例作为教学的第一章。Let's enjoy :P.

特点

  1. 使用单例的类,有且仅有一个实例对象。
  2. 使用单例的类的实例对象由该类自行创建。
  3. 单例类需提供一个对外的访问接口供外部调用方进行调用,可以通过该类访问到该类的实例对象。

适用场景

1.需要频繁创建的类,使用单例可以降低系统内存压力。 2. 某些具有唯一性的类,比如接口模块的集合,一个系统有且仅有一个相同模块的接口集合。从逻辑上而言,使用单例应该是单一控制的类或者方法。 3. 当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。

Good & Bad

Good

  1. 使用单例可以来降低内存压力,减少内存开销。
  2. 单例模式可以全局共享一个实例,可以避免对资源的浪费,优化资源的访问。

Bad

  1. 单例模式通常都将功能代码写于同一个类中,如果业务逻辑设计不合理,拓展起来比较困难,都需要修改其原本的实体对象,违背了开闭原则。
  2. 在并发的场景下,由于全局共享一个实例对象,调试困难。

How

  1. 构造函数私有化,确保用户无法通过 new 来进行实例化。

image.png

类型

可分为饿汉型和懒汉型两种,主要区别在于创建实例对象的时机不同。

饿汉型

创建类时就生成好了实例对象。

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 中返回其中一个供调用方使用。

  • 随机: 实际上这个返回策略可以自己决定
  • 有限: 主要是指在类里面规定好了实例个数,不因运行时其他状态而改变。

image.png

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:

设计模式文章 Index

reference:

  1. singleton wikipedia
  2. online usage of the pattern in typescript