JS常用设计模式汇总

发布于:2025-06-21 ⋅ 阅读:(15) ⋅ 点赞:(0)

1、基于类的单例模式

// 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;

使用方式

// 使用方可以决定何时初始化
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习惯的实现:

// 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
};

使用方式:

import pageManager from './pageManager';

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

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

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

// 使用示例
// 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 })
  };
};

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

基本使用

// 使用示例
import { createPageGenerator } from './createPageGenerator';

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

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

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

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)

// 主题(被观察者)
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)、数据绑定

网站公告

今日签到

点亮在社区的每一天
去签到