超简单发布订阅模式讲解

2023-10-11  本文已影响0人  码农说

发布订阅模式

发布订阅模式和观察者模式是两种常见的设计模式,用于处理事件和通信。在本文中,我们将逐步构建一个功能完善的EventEmitter,并通过这一过程来深入理解发布订阅模式。

简洁的版本

我们构建一个简单的发布订阅模型:

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

  // 订阅事件
  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(listener);
  }

  // 卸载事件
  off(event, listener) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(l => l !== listener);
    }
  }

  // 发布事件
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(listener => listener(data));
    }
  }
}

我们创建了一个EventEmitter类,其中包括了onoffemit方法,分别用于订阅事件、卸载事件和发布事件。

代码流程解释:

升级版:添加一次性调用

我们引入了一次性订阅,也就是once方法。

// ...

  // 一次性订阅
  once(event, listener) {
    const onceWrapper = data => {
      listener(data);
      this.off(event, onceWrapper);
    };
    this.on(event, onceWrapper);
  }

流程解释:

进阶版:支持连续调用

让我们的EventEmitter支持连续调用,这样我们可以在一个链中连续执行多个方法。

class EventEmitter {
  // ...

  // 订阅事件,支持连续调用
  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(listener);
    return this;
  }

  // 卸载事件,支持连续调用
  off(event, listener) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(l => l !== listener);
    }
    return this;
  }

  // 一次性订阅,支持连续调用
  once(event, listener) {
    const onceWrapper = data => {
      listener(data);
      this.off(event, onceWrapper);
    };
    this.on(event, onceWrapper);
    return this;
  }
}

流程解释:

这三个函数的返回使得我们可以像下面这样连续调用它们:

eventEmitter
  .on('event1', listener1)
  .on('event2', listener2)
  .once('event3', listener3)
  .off('event4', listener4);

通过连续调用,我们可以在一个链中轻松执行多个操作。

完整版:添加事件缓存

在第四步中,我们引入了事件缓存,允许查看已经订阅的事件。

// ...

  // 获取事件列表
  getEvents() {
    return Object.keys(this.events);
  }
}

代码流程解释:

发布订阅模式与观察者模式区别

主要区别:

观察者模式示例:

// 主题
class Subject {
  constructor() {
    this.observers = [];
  }

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

  removeObserver(observer) {
    const index = this.observers.indexOf(observer);
    if (index !== -1) {
      this.observers.splice(index, 1);
    }
  }

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

// 观察者
class Observer {
  update(message) {
    console.log(`Received message: ${message}`);
  }
}

const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();

subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notify("Hello, observers!");

在我们上面的介绍中,发布订阅模式使用了中介者来处理事件的发布和订阅,而观察者模式是一对多的关系,主题对象直接通知观察者。

总结

通过逐步构建一个支持连续调用的事件模型,我们介绍了基本的发布订阅模式。同时也简单介绍了发布订阅模式和观察者模式之间差异。发布订阅模式更加灵活,支持多对多关系,适用于更多的场景,而观察者模式是一对多关系,明确定义了观察者的接口。最后希望本文对大家理解发布订阅模式有帮助。

上一篇 下一篇

猜你喜欢

热点阅读