设计模式入门:单例模式

用通俗易懂的方式讲解单例模式,包括实现方式、应用场景和注意事项

4 分钟阅读
小明

设计模式入门:单例模式

今天小明来聊聊设计模式中最简单也最常用的一个 —— 单例模式(Singleton Pattern)

什么是单例模式?

用一句话解释:确保一个类只有一个实例,并提供全局访问点。

生活中的例子

想象一下这些场景:

  • 🖨️ 打印机管理器 - 整个办公室只需要一个
  • ⚙️ 配置管理 - 应用程序只需要一份配置
  • 📊 日志记录器 - 所有模块共用一个日志系统

这些都是单例模式的典型应用!

TypeScript 实现

基础实现

class Singleton {
  private static instance: Singleton | null = null
  
  // 私有构造函数,防止外部 new
  private constructor() {
    console.log('Singleton 实例被创建')
  }
  
  // 获取实例的静态方法
  public static getInstance(): Singleton {
    if (!Singleton.instance) {
      Singleton.instance = new Singleton()
    }
    return Singleton.instance
  }
  
  public doSomething(): void {
    console.log('执行操作')
  }
}

// 使用
const s1 = Singleton.getInstance()
const s2 = Singleton.getInstance()

console.log(s1 === s2) // true - 同一个实例

实际应用:配置管理器

interface AppConfig {
  apiUrl: string
  debug: boolean
  theme: 'light' | 'dark'
}

class ConfigManager {
  private static instance: ConfigManager | null = null
  private config: AppConfig
  
  private constructor() {
    // 默认配置
    this.config = {
      apiUrl: 'https://api.xiaoming.wiki',
      debug: false,
      theme: 'dark'
    }
  }
  
  public static getInstance(): ConfigManager {
    if (!ConfigManager.instance) {
      ConfigManager.instance = new ConfigManager()
    }
    return ConfigManager.instance
  }
  
  public get<K extends keyof AppConfig>(key: K): AppConfig[K] {
    return this.config[key]
  }
  
  public set<K extends keyof AppConfig>(key: K, value: AppConfig[K]): void {
    this.config[key] = value
  }
}

// 在任何地方使用
const config = ConfigManager.getInstance()
console.log(config.get('theme')) // 'dark'
config.set('debug', true)

单例模式的优缺点

✅ 优点

  1. 资源节约 - 只创建一个实例,减少内存开销
  2. 全局访问 - 提供统一的访问点
  3. 状态共享 - 多处代码可以共享同一状态

❌ 缺点

  1. 测试困难 - 单例状态在测试间可能相互影响
  2. 隐藏依赖 - 使用单例的代码有隐式依赖
  3. 并发问题 - 多线程环境需要特殊处理

现代 JavaScript 中的单例

在 ES6 模块系统中,实现单例变得更简单:

// config.ts
const config = {
  apiUrl: 'https://api.xiaoming.wiki',
  debug: false,
  theme: 'dark' as const
}

export default config

由于 ES 模块只会被加载一次,所以 config 天然就是单例!

小明的冷笑话

单例模式和程序员有什么共同点?

都是"单身狗",而且都觉得自己是独一无二的! 🐕

什么时候使用单例?

适合使用的场景:

  • 配置管理
  • 日志记录
  • 数据库连接池
  • 缓存管理

不适合使用的场景:

  • 需要多个独立实例
  • 对象需要频繁创建销毁
  • 单元测试要求隔离

总结

单例模式是最简单的设计模式之一,但也要谨慎使用。记住:

不要因为它简单就滥用,每个设计模式都有其适用场景。


下篇文章,小明将介绍另一个常用的设计模式 —— 工厂模式,敬请期待!

Happy Coding! 🚀