Blog 项目中的 TypeScript 单例模式详解与实现方式对比

1. 介绍

单例模式的核心是确保一个类只有一个实例,并提供全局访问点。

设计要素 作用说明
私有构造函数 禁止外部使用 new 创建实例 (private constructor() {})
静态私有属性 在类内部存储唯一实例 (private static instance: Singleton;)
静态访问方法 提供全局访问入口 (public static getInstance())
延迟初始化 首次调用时才创建实例(节约资源)
类型安全 TS 类型系统确保实例访问安全
线程安全 在 JS/TS 单线程环境中天然安全(多线程环境需额外处理)

核心遵循的原则

  1. 单一职责原则 (SRP)
    单例模式确保一个类只负责管理自己的唯一实例创建和访问,职责单一明确。
  2. 开闭原则 (OCP)
    通过私有构造函数和静态方法的设计,单例类对修改关闭(不能随意创建多个实例),但可以通过继承或扩展功能对扩展开放。
  3. 依赖倒置原则 (DIP)
    客户端代码依赖于单例类提供的抽象接口,而不是具体的实例化细节。

2. 实现

2.1 经典实现(静态属性 + 私有构造)

// 经典实现(静态属性 + 私有构造)
export class Singleton {
  // 1. 静态属性保存唯一实例
  private static instance: Singleton;
  // 2. 私有构造函数,防止外部实例化
  private constructor() {}
  // 3. 全局访问点
  public static getInstance(): Singleton {
    if (!Singleton.instance) {
      Singleton.instance = new Singleton();
    }
    return Singleton.instance;
  }
  // 示例方法
  public log(message:string):void {
    console.log(`[Singleton] ${message}`)
  }
}

// 使用
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // true
instance1.log("Hello Singleton"); // [Singleton] Hello Singleton

2.2 懒汉式

class EagerSingleton {
  // 类加载时立即创建实例
  private static readonly instance: EagerSingleton = new EagerSingleton();
  // 私有构造函数,防止外部实例化
  private constructor() {}
  // 全局访问点
  public static getInstance(): EagerSingleton {
    return this.instance;
  }
}

// 使用
const eagerInstance1 = EagerSingleton.getInstance();
const eagerInstance2 = EagerSingleton.getInstance();

console.log(eagerInstance1 === eagerInstance2); // true
console.log("Hello EagerSingleton"); // [EagerSingleton] Hello EagerSingleton

2.3 使用命名空间(非类实现)

namespace SingletonNamespace {
  // 私有实例
  let instance: any;
  // 通过函数暴露实例
  export function getInstance<T>(c: {new(): T}): T {
    if (!instance) {
      instance = new c();
    }
    return instance;
  }
}

class MyService {
  constructor() {
    console.log("MyService constructor");
  }
}

// 使用
const service1 = SingletonNamespace.getInstance(MyService);
const service2 = SingletonNamespace.getInstance(MyService);
console.log(service1 === service2); // true
© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容