设计模式 单例模式

90 阅读3分钟

单例模式(Singleton Pattern)是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。单例模式在需要控制资源的唯一性和全局共享时非常有用,例如配置对象、日志对象、线程池、数据库连接等。

单例模式的设计理念

  1. 唯一实例

    • 确保一个类只有一个实例存在。通过限制类的实例化次数,防止创建多个实例,从而节约资源和保证一致性。
  2. 全局访问点

    • 提供一个全局访问点,使得可以从程序的任何地方访问这个唯一实例。通常通过一个静态方法或属性来实现。
  3. 延迟实例化

    • 单例模式通常使用延迟实例化(Lazy Initialization)技术,即在第一次需要时创建实例,而不是在程序启动时创建。这可以提高程序的启动性能。

单例模式的实现步骤

  1. 私有化构造函数

    • 将类的构造函数设为私有,防止外部通过new关键字创建实例。
  2. 提供一个静态方法或属性

    • 提供一个静态方法或属性,用于获取类的唯一实例。如果实例不存在,则创建一个新的实例;如果实例已经存在,则返回该实例。
  3. 存储唯一实例

    • 在类内部存储一个静态的唯一实例引用。

单例模式的实现示例

以下是JavaScript中单例模式的实现示例:

class Singleton {
    // 存储唯一实例的静态属性
    static instance = null;

    // 私有化构造函数
    constructor() {
        if (Singleton.instance) {
            throw new Error("Singleton class cannot be instantiated more than once.");
        }
        Singleton.instance = this;
        // 初始化其他属性
        this.value = Math.random();
    }

    // 获取唯一实例的静态方法
    static getInstance() {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }

    // 其他方法
    getValue() {
        return this.value;
    }
}

// 使用示例
try {
    const instance1 = Singleton.getInstance();
    console.log(instance1.getValue());

    const instance2 = Singleton.getInstance();
    console.log(instance2.getValue());

    // 验证两个实例是否相同
    console.log(instance1 === instance2); // 输出: true
} catch (e) {
    console.error(e.message);
}

设计理念的优点

  1. 控制实例数量

    • 确保一个类只有一个实例,避免资源浪费和不一致性。
  2. 全局访问

    • 提供一个全局访问点,使得可以从程序的任何地方访问这个实例,方便管理和共享资源。
  3. 延迟加载

    • 通过延迟实例化,提高程序的启动性能,只有在需要时才创建实例。

设计理念的缺点

  1. 难以扩展

    • 单例模式限制了类的实例化,可能会导致难以扩展和测试。
  2. 全局状态

    • 单例模式引入了全局状态,可能会导致隐藏的依赖关系和难以调试的问题。
  3. 并发问题

    • 在多线程环境下,需要确保单例实例的创建是线程安全的,可能会引入复杂的同步机制。

单例模式是一种简单而强大的设计模式,但在使用时需要谨慎考虑其适用性和潜在问题。