单例模式

创建型模式
常用程度: 高
难度: 简单

单例模式确保一个类只有一个实例,并提供一个全局访问点。在前端开发中常用于全局状态管理、缓存、日志记录等场景。

核心思想

单例模式通过限制类的实例化次数为一次,确保在整个应用程序中只有一个实例存在。这有助于节省内存资源,同时提供统一的访问入口。

JavaScript实现

单例模式实现
// ES6实现单例模式
class Singleton {
  constructor() {
    if (!Singleton.instance) {
      this.data = [];
      this.config = {};
      Singleton.instance = this;
    }
    return Singleton.instance;
  }
  
  addData(item) {
    this.data.push(item);
  }
  
  getData() {
    return this.data;
  }
  
  setConfig(key, value) {
    this.config[key] = value;
  }
  
  getConfig(key) {
    return this.config[key];
  }
}

// 使用示例
const instance1 = new Singleton();
const instance2 = new Singleton();

console.log(instance1 === instance2); // true,两个变量引用同一个实例

instance1.addData('item1');
console.log(instance2.getData()); // ['item1'],共享数据

// 更简洁的实现方式(闭包)
const createSingleton = () => {
  let instance;
  
  const init = () => {
    // 私有变量和方法
    let privateData = [];
    
    // 公有方法
    return {
      add: (item) => privateData.push(item),
      getAll: () => [...privateData],
      clear: () => privateData = []
    };
  };
  
  return {
    getInstance: () => {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  };
};

const singleton = createSingleton();
const app1 = singleton.getInstance();
const app2 = singleton.getInstance();

console.log(app1 === app2); // true

优点

  • 确保全局只有一个实例,节省内存
  • 提供全局访问点,便于管理共享资源
  • 避免重复创建相同对象
  • 便于实现延迟初始化

缺点

  • 可能导致全局状态污染
  • 难以进行单元测试
  • 违反单一职责原则
  • 可能隐藏类之间的依赖关系

使用场景

  • 全局配置管理
  • 缓存系统
  • 日志记录器
  • 状态管理(如Redux Store)
  • 对话框/模态框管理
  • 数据库连接池

工厂模式

创建型模式
常用程度: 高
难度: 中等

工厂模式提供了一种创建对象的方式,而无需指定具体的类。它将对象的创建逻辑封装起来,使代码更加灵活和可维护。

核心思想

工厂模式定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法让类的实例化延迟到子类,增加了代码的灵活性和可扩展性。

JavaScript实现

工厂模式实现
// 简单工厂模式
class Button {
  constructor(text) {
    this.text = text;
  }
  
  render() {
    return `<button>${this.text}</button>`;
  }
}

class Input {
  constructor(placeholder) {
    this.placeholder = placeholder;
  }
  
  render() {
    return `<input placeholder="${this.placeholder}" />`;
  }
}

class FormFactory {
  static createElement(type, options) {
    switch (type) {
      case 'button':
        return new Button(options.text);
      case 'input':
        return new Input(options.placeholder);
      default:
        throw new Error('Unknown element type');
    }
  }
}

// 使用示例
const button = FormFactory.createElement('button', { text: '点击我' });
const input = FormFactory.createElement('input', { placeholder: '请输入...' });

console.log(button.render()); // "<button>点击我</button>"
console.log(input.render()); // "<input placeholder='请输入...' />"

// 工厂方法模式
class Dialog {
  createButton() {
    throw new Error('必须实现 createButton 方法');
  }
  
  render() {
    const button = this.createButton();
    return `Dialog with ${button.render()}`;
  }
}

class WindowsDialog extends Dialog {
  createButton() {
    return new WindowsButton();
  }
}

class <