Skip to content

[toc]

推导链

Q1: 发布订阅是什么? → 事件中心:on 订阅、emit 发布、off 取消 → 发布者和订阅者不直接通信,通过事件中心

Q2: 观察者模式区别? → 观察者直接订阅目标,目标直接通知观察者 → 没有中间的事件中心

Q3: 核心数据结构? → 发布订阅:{ eventName: [cb1, cb2] } → 观察者:observers: [observer1, observer2]

发布订阅模式

javascript
class EventEmitter {
    constructor() {
        // 调度中心
        this.events = {};
    }
    // 1. 订阅事件
    on(eventName, callback) {
        if (!this.events[eventName]) {
            this.events[eventName] = [];
        }
        this.events[eventName].push(callback);
    }
    // 2. 发布事件
    emit(eventName, ...args) {
        const callbacks = this.events[eventName];
        if (callbacks) {
            callbacks.forEach(cb => cb.apply(this, args));
        }
    }
    // 3. 取消订阅
    off(eventName, callback) {
        const callbacks = this.events[eventName];
        if (callbacks) {
            this.events[eventName] = callbacks.filter(cb => cb !== callback);
        }
    }
    // 4. 只执行一次
    once(eventName, callback) {
        const oneTimeFn = (...args) => {
            callback.apply(this, args);
            this.off(eventName, oneTimeFn);
        };
        this.on(eventName, oneTimeFn);
    }
}

// 测试
const bus = new EventEmitter();

// 订阅消息
const handleMsg = (data) => console.log('收到消息:', data);
bus.on('message', handleMsg);

// 发布消息
bus.emit('message', 'Hello World!'); // 打印: 收到消息: Hello World!

// 取消订阅后再次发布
bus.off('message', handleMsg);
bus.emit('message', '听得到了吗?'); // 无输出

观察者模式

javascript
// 被观察者 (Subject)
class Subject {
  constructor() {
    this.observers = []; // 存储所有观察者
  }
  // 添加观察者
  add(observer) {
    this.observers.push(observer);
  }
  remove(observer) {
    this.observers = this.observers.filter(o => o !== observer)
  }
  // 通知所有观察者
  notify(message) {
    this.observers.forEach(observer => {
      observer.update(message);
    });
  }
}

//  观察者 (Observer)
class Observer {
  constructor(name) {
    this.name = name;
  }
  // 更新方法,被 Subject 调用
  update(message) {
    console.log(`${this.name} 收到消息: ${message}`);
  }
}

// 创建被观察者
const subject = new Subject();
// 创建观察者
const obs1 = new Observer("A");
const obs2 = new Observer("B");

subject.add(obs1);
subject.add(obs2);

// 被观察者发布消息
subject.notify("hello world!");