JS常用设计模式汇总

1、基于类的单例模式

javascript 复制代码
// PageManager.js
class PageManager {
  constructor(config) {
    if (!PageManager.instance) {
      this.config = config;
      this.initialized = false;
      PageManager.instance = this;
      
      this.init();
    }
    return PageManager.instance;
  }

  init() {
    if (this.initialized) return;
    
    console.log('Initializing with config:', this.config);
    // 实际初始化逻辑
    this.initialized = true;
  }

  generatePage(instruction) {
    if (!this.initialized) {
      throw new Error('PageManager not initialized');
    }
    
    const page = {
      ...this.config,
      ...instruction,
      id: Date.now()
    };
    
    console.log('Generated page:', page);
    return page;
  }

  // 更新配置(新增方法)
  updateConfig(newConfig) {
    Object.assign(this.config, newConfig);
  }

  // 获取实例的静态方法(推荐方式)
  static getInstance(config) {
    if (!PageManager.instance) {
      PageManager.instance = new PageManager(config);
    }
    return PageManager.instance;
  }
}

// 不立即初始化,而是导出类
export default PageManager;

使用方式

javascript 复制代码
// 使用方可以决定何时初始化
import PageManager from './PageManager';

// 第一次获取实例时初始化(推荐方式)
const pageManager = PageManager.getInstance({
  defaultTemplate: 'advanced',
  baseStyles: true
});

// 生成页面
const homePage = pageManager.generatePage({ 
  title: 'Home', 
  content: 'Welcome' 
});

// 后续获取仍然是同一个实例
const sameManager = PageManager.getInstance();
console.log(pageManager === sameManager); // true

// 可以更新配置
pageManager.updateConfig({
  defaultTemplate: 'custom'
});

2、更优雅的变体:模块模式单例

如果你更喜欢模块模式而不是类,这里有一个更符合JavaScript习惯的实现:

javascript 复制代码
// pageManager.js
let instance = null;
let config = {};
let initialized = false;

const init = (initialConfig) => {
  if (initialized) {
    console.warn('PageManager already initialized');
    return;
  }
  
  config = {
    defaultTemplate: 'standard',
    ...initialConfig
  };
  
  initialized = true;
  console.log('PageManager initialized with config:', config);
};

const generatePage = (instruction) => {
  if (!initialized) throw new Error('PageManager not initialized');
  
  return {
    ...config,
    ...instruction,
    id: `page-${Date.now()}`
  };
};

const updateConfig = (newConfig) => {
  Object.assign(config, newConfig);
};

// 导出单例对象
export default {
  init,
  generatePage,
  updateConfig
};

使用方式:

javascript 复制代码
import pageManager from './pageManager';

// 在使用前初始化
pageManager.init({
  defaultTemplate: 'custom'
});

// 使用单例
const page = pageManager.generatePage({ title: 'About' });

3、使用工厂函数(更灵活)

js 复制代码
// 使用示例
// createPageGenerator.js
export const createPageGenerator = (initialConfig) => {
  const config = {
    defaultTemplate: 'standard',
    basePath: '/',
    ...initialConfig
  };
  
  const generate = (instruction) => {
    const pageId = `${config.basePath}${instruction.slug || `page-${Date.now()}`}`;
    
    return {
      ...config,
      ...instruction,
      id: pageId,
      fullPath: `${config.basePath}${instruction.path || ''}`,
      createdAt: new Date()
    };
  };
  
  const updateConfig = (newConfig) => {
    Object.assign(config, newConfig);
  };
  
  return {
    generate,
    updateConfig,
    getConfig: () => ({ ...config })
  };
};

// 使用示例
// 可以创建多个实例或单个实例使用

基本使用

js 复制代码
// 使用示例
import { createPageGenerator } from './createPageGenerator';

// 1. 创建实例(简单配置)
const simpleGenerator = createPageGenerator();
const page1 = simpleGenerator.generate({ title: 'Home' });
console.log(page1);

4、发布-订阅模式 (Pub-Sub Pattern)

用途:观察者模式的变体,使用主题/通道概念解耦发布者和订阅者。

js 复制代码
class EventBus {
  constructor() {
    this.events = {};
  }

  subscribe(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  publish(eventName, data) {
    if (this.events[eventName]) {
      this.events[eventName].forEach(callback => callback(data));
    }
  }

  unsubscribe(eventName, callback) {
    if (this.events[eventName]) {
      this.events[eventName] = this.events[eventName].filter(
        cb => cb !== callback
      );
    }
  }
}

// 使用
const bus = new EventBus();

// 订阅
const logData = data => console.log('Received:', data);
bus.subscribe('dataUpdate', logData);

// 发布
bus.publish('dataUpdate', { newData: 123 });

// 取消订阅
bus.unsubscribe('dataUpdate', logData);

// 实际应用:Vue的EventBus、组件间通信

5、观察者模式 (Observer Pattern)

js 复制代码
// 主题(被观察者)
class Subject {
  constructor() {
    this.observers = [];
  }

  subscribe(observer) {
    this.observers.push(observer);
  }

  unsubscribe(observer) {
    this.observers = this.observers.filter(obs => obs !== observer);
  }

  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

// 观察者
class Observer {
  update(data) {
    console.log('Observer received:', data);
  }
}

// 使用
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();

subject.subscribe(observer1);
subject.subscribe(observer2);

subject.notify('Hello observers!'); // 两个观察者都会收到通知

// 实际应用:事件系统、状态管理(如Redux)、数据绑定
相关推荐
Meteors.5 分钟前
23种设计模式——外观模式(Facade Pattern)详解
设计模式·外观模式
胖虎16 分钟前
iOS中的设计模式(九)- 外观模式 用外观模式点一份外卖:Swift 实战讲解
设计模式·外观模式
一匹电信狗16 分钟前
【LeetCode_160】相交链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
软件技术NINI24 分钟前
MATLAB疑难诊疗:从调试到优化的全攻略
javascript·css·python·html
曦樂~28 分钟前
【Qt】信号与槽(Signal and Slot)- 简易计算器
开发语言·数据库·qt
歪歪10037 分钟前
React Native开发Android&IOS流程完整指南
android·开发语言·前端·react native·ios·前端框架
知识分享小能手39 分钟前
uni-app 入门学习教程,从入门到精通,uni-app组件 —— 知识点详解与实战案例(4)
前端·javascript·学习·微信小程序·小程序·前端框架·uni-app
yaoxin5211231 小时前
212. Java 函数式编程风格 - Java 编程风格转换:命令式 vs 函数式(以循环为例)
java·开发语言
wangqiaowq1 小时前
ImmutableList.of() 是 Google Guava 库 提供的一个静态工厂方法,用于创建一个不可变的(immutable)列表。
开发语言·windows·python
苏打水com1 小时前
从 HTML/CSS/JS 到 React:前端进阶的平滑过渡指南
前端·javascript·html