JavaScript 面向对象编程:单例模式

114 阅读2分钟

单例模式(Singleton Pattern)是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。

单例模式的核心特点

  1. 唯一性:确保一个类只有一个实例存在
  2. 全局访问:提供全局访问该实例的方法
  3. 延迟实例化:通常只在第一次使用时创建实例

JavaScript 实现单例模式的几种方式

1. 对象字面量实现(最简单的单例)

const singleton = {
  property: "value",
  method: function() {
    console.log("I am a method");
  }
};

这本质上就是一个单例,因为对象字面量在JavaScript中本身就是唯一的。

2. 使用闭包和立即执行函数(IIFE)

const Singleton = (function() {
  let instance;
  
  function createInstance() {
    const object = new Object("I am the instance");
    return object;
  }
  
  return {
    getInstance: function() {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true

3. ES6 Class 实现

class Singleton {
  constructor() {
    if (!Singleton.instance) {
      Singleton.instance = this;
    }
    return Singleton.instance;
  }
  
  static getInstance() {
    if (!this.instance) {
      this.instance = new Singleton();
    }
    return this.instance;
  }
}

const instance1 = new Singleton();
const instance2 = new Singleton();
const instance3 = Singleton.getInstance();
console.log(instance1 === instance2); // true
console.log(instance1 === instance3); // true

4. 模块化的单例模式

在现代JavaScript中,使用ES6模块系统可以更简单地实现单例:

// singleton.js
let instance;

class MySingleton {
  constructor() {
    if (instance) {
      throw new Error("You can only create one instance!");
    }
    instance = this;
  }
  
  // 其他方法...
}

const singletonInstance = Object.freeze(new MySingleton());
export default singletonInstance;

然后在使用时:

import singletonInstance from './singleton.js';

单例模式的应用场景

  1. 全局状态管理:如Redux中的store
  2. 配置对象:应用中只需要一个配置对象
  3. 缓存系统:全局共享的缓存
  4. 日志系统:应用中只需要一个日志记录器
  5. 数据库连接池:通常只需要一个连接池实例

单例模式的优缺点

优点

  • 延迟初始化(节省资源)
  • 严格控制实例数量
  • 全局访问方便

缺点

  • 全局状态可能导致代码耦合
  • 难以测试(因为全局状态)
  • 可能违反单一职责原则

单例模式在JavaScript中非常常见,但需要谨慎使用,避免过度使用导致代码难以维护。