全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 8 分钟 ✍️ juanwangdev

观察者模式与事件驱动

观察者模式是前端最常用的设计模式之一,事件驱动是其典型应用形式。

核心概念

观察者模式

定义对象间一对多的依赖关系,当被观察者状态改变时,所有依赖者收到通知并自动更新。

基本结构

  • Subject(主题):被观察对象,维护观察者列表
  • Observer(观察者):订阅主题,响应状态变化

基础实现

手动实现

JavaScript
class Subject {
  constructor() {
    this.observers = [];
  }

  subscribe(observer) {
    this.observers.push(observer);
    return () => {
      this.observers = this.observers.filter(o => o !== observer);
    };
  }

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

class Observer {
  update(data) {
    console.log('Received:', data);
  }
}

// 使用
const subject = new Subject();
const observer = new Observer();
subject.subscribe(observer);
subject.notify('Hello');

现代实现

JavaScript
class EventEmitter {
  constructor() {
    this.events = new Map();
  }

  on(event, callback) {
    if (!this.events.has(event)) {
      this.events.set(event, new Set());
    }
    this.events.get(event).add(callback);
    return () => this.off(event, callback);
  }

  off(event, callback) {
    this.events.get(event)?.delete(callback);
  }

  emit(event, ...args) {
    this.events.get(event)?.forEach(cb => cb(...args));
  }

  once(event, callback) {
    const wrapper = (...args) => {
      callback(...args);
      this.off(event, wrapper);
    };
    this.on(event, wrapper);
  }
}

// 使用
const emitter = new EventEmitter();
emitter.on('data', (msg) => console.log(msg));
emitter.emit('data', 'Hello World');

事件驱动架构

DOM事件模型

JavaScript
// 原生事件:浏览器内置的事件驱动
document.addEventListener('click', (e) => {
  console.log('Clicked:', e.target);
});

// 自定义事件
const customEvent = new CustomEvent('userAction', {
  detail: { action: 'login', userId: 123 }
});
element.dispatchEvent(customEvent);
element.addEventListener('userAction', (e) => {
  console.log('User action:', e.detail);
});

Node.js事件

JavaScript
const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b);
});
myEmitter.emit('event', 'a', 'b');

实际应用场景

状态管理

JavaScript
class Store {
  constructor(initialState) {
    this.state = initialState;
    this.listeners = new Set();
  }

  getState() {
    return this.state;
  }

  setState(newState) {
    this.state = { ...this.state, ...newState };
    this.listeners.forEach(listener => listener(this.state));
  }

  subscribe(listener) {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }
}

// 使用
const store = new Store({ count: 0 });
store.subscribe(state => console.log('State:', state));
store.setState({ count: 1 });

组件通信

JavaScript
// 全局事件总线(Vue)
const eventBus = {
  events: {},
  on(event, callback) {
    (this.events[event] || (this.events[event] = [])).push(callback);
  },
  emit(event, ...args) {
    (this.events[event] || []).forEach(cb => cb(...args));
  }
};

// 跨组件通信
eventBus.on('userLogin', (user) => { /* 处理登录 */ });
eventBus.emit('userLogin', { id: 1, name: 'Alice' });

异步流程控制

JavaScript
class TaskQueue {
  constructor() {
    this.emitter = new EventEmitter();
    this.queue = [];
  }

  add(task) {
    this.queue.push(task);
    this.emitter.emit('taskAdded', task);
  }

  process() {
    while (this.queue.length) {
      const task = this.queue.shift();
      task();
      this.emitter.emit('taskCompleted', task);
    }
    this.emitter.emit('allCompleted');
  }
}

发布-订阅模式对比

特性观察者模式发布-订阅模式
耦合度Subject直接通知Observer通过Event Channel中转
通信方式直接通信间接通信
适用场景一对多、紧密关联分布式、解耦场景
实现复杂度简单相对复杂
JavaScript
// 发布-订阅模式
class PubSub {
  constructor() {
    this.topics = {};
  }

  publish(topic, message) {
    (this.topics[topic] || []).forEach(sub => sub(message));
  }

  subscribe(topic, callback) {
    if (!this.topics[topic]) this.topics[topic] = [];
    this.topics[topic].push(callback);
    return () => {
      this.topics[topic] = this.topics[topic].filter(cb => cb !== callback);
    };
  }
}

观察者模式中Subject和Observer直接交互;发布-订阅模式通过消息调度中心解耦。

要点总结

  1. 核心结构:Subject维护Observer列表,状态变更时通知
  2. 事件驱动:观察者模式的前端实践形式
  3. 解耦优势:发布者与订阅者松耦合,易扩展
  4. 典型应用:状态管理、组件通信、异步流程
  5. 注意事项:及时取消订阅,避免内存泄漏

存放路径:articles/JS/专家/设计模式与架构思想/观察者模式与事件驱动.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 模块化设计原则
下一篇 → 设计模式基础
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库