猫码程序员让前端飞

谈谈观察者模式和发布订阅模式

2020-04-08  本文已影响0人  ComfyUI

这两个东西捋清楚需要点耐心。

1、观察者vs发布订阅

2、观察者模式

// 观察者(租客)
class Observer {
  constructor(subject) {
    this.subject = subject;
  }
  notify() {
    console.log(`收到一条房东的消息,${this.subject}空了!!!`);
  }
}
// 主题(房东)
class Subject {
  // 根据户型的不同收集相应的订阅者
  constructor() {
    this.subjectList = {};
  }
  // 订阅
  add(subject, observer) {
    if (!this.subjectList[subject]) {
      this.subjectList[subject] = [];
    }
    this.subjectList[subject].push(observer);
  }
  // 解除订阅
  remove(subject, observer) {
    this.subjectList[subject].forEach((item, index) => {
      if (item === observer) {
        this.subjectList[subject].splice(index, 1);
      }
    });
  }
  // 触发事件
  fire(subject) {
    this.subjectList[subject].forEach((item) => item.notify());
  }
}
// 不同的用户想关注别墅(big)、`洋房(medium)`...等不同的户型
const observerA = new Observer("bigHouse");
const observerB = new Observer("mediumHouse");
const observerC = new Observer("smallHouse");
// 把这3个观察者添加到相应的分组
const subjects = new Subject();
subjects.add("bigHouse", observerA);
subjects.add("mediumHouse", observerB);
subjects.add("smallHouse", observerC);
// 某一天
subjects.fire("bigHouse"); // 收到一条房东的消息,bigHouse空了!!!
// 又某一天
subjects.fire("mediumHouse"); // 收到一条房东的消息,mediumHouse空了!!!
// 再某一天
subjects.fire("smallHouse"); // 收到一条房东的消息,smallHouse空了!!!
// 观察者(租客)
class Observer {
  constructor(subject) {
    this.subject = subject;
  }
  notify() {
    console.log(`收到一条房东的消息,${this.subject}空了!!!`);
  }
}

// 主题(房东)
class Subject {
  // 根据户型的不同收集相应的订阅者
  constructor() {
    this.subjectList = {};
  }
  // 订阅
  add(subject, observer) {
    if (!this.subjectList[subject]) {
      this.subjectList[subject] = [];
    }
    this.subjectList[subject].push(observer);
  }
  // 解除订阅
  remove(subject, observer) {
    this.subjectList[subject].forEach((item, index) => {
      if (item === observer) {
        this.subjectList[subject].splice(index, 1);
      }
    });
  }
  // 触发事件
  fire(subject) {
    this.subjectList[subject].forEach((item) => item.notify());
  }
}

// 不同的用户想关注别墅(big)、`洋房(medium)`...等不同的户型
const observerA = new Observer("bigHouse");
const observerB = new Observer("mediumHouse");
const observerC = new Observer("smallHouse");

// 把这3个观察者添加到相应的分组
const subjects = new Subject();
subjects.add("bigHouse", observerA);
subjects.add("mediumHouse", observerB);
subjects.add("smallHouse", observerC);

// 某一天
subjects.fire("bigHouse"); // 收到一条房东的消息,bigHouse空了!!!
// 又某一天
subjects.fire("mediumHouse"); // 收到一条房东的消息,mediumHouse空了!!!
// 再某一天
subjects.fire("smallHouse"); // 收到一条房东的消息,smallHouse空了!!!

3、发布订阅模式

(1)理解

(2)实践

class EventBus {
  constructor() {
    // 定义事件池
    // 数据结构应该长这样:{<事件队列名>:<要执行的事件队列>}
    // {'buy': ['func1','func2','func3']}
    this.events = {};
  }

  /**
   * 订阅
   * @param {事件队列名} name
   * @param {事件函数} func
   */
  on(name, func) {
    if (!this.events[name]) {
      this.events[name] = [];
    }
    this.events[name].push(func);
  }

  /**
   * 发布
   * @param {事件队列名} args
   * @param {传入参数} args
   */
  emit(name, ...args) {
    if (!this.events[name]) {
      return;
    }
    this.events[name].forEach(item => {
      item.apply(this, args);
    });
  }

  /**
   * 删除
   * @param {事件队列名} args
   */
  remove(name) {
    if (this.events[name]) {
      delete this.events[name];
    }
  }
}
// 实例化
const bus = new EventBus();

// 不同租客订阅了不同需求房型
bus.on("bigHouse", function (value) {
  console.log(`A收到了一条消息:${value}`);
});

bus.on("mediumHouse", function (value) {
  console.log(`B收到了一条消息:${value}`);
});

bus.on("smallHouse", function (value) {
  console.log(`C收到了一条消息:${value}`);
});
// 某天房东通过中介发布了一条消息
bus.emit("bigHouse", "别墅有房了"); // A收到了一条消息:别墅有房了
// 又某一天
bus.emit("mediumHouse", "洋房有房了"); // B收到了一条消息:洋房有房了
// 再某一天。。。。
bus.emit("smallHouse", "小平层有房了"); // C收到了一条消息:小平层有房了
class EventBus {
  constructor() {
    // 定义事件池
    // 数据结构应该长这样:{<事件队列名>:<要执行的事件队列>}
    // {'say': ['func1','func2','func3']}
    this.events = {};
  }

  /**
   * 订阅
   * @param {事件队列名} name
   * @param {事件函数} func
   */
  on(name, func) {
    if (!this.events[name]) {
      this.events[name] = [];
    }
    this.events[name].push(func);
  }

  /**
   * 发布
   * @param {事件队列名} args
   * @param {传入参数} args
   */
  emit(name, ...args) {
    if (!this.events[name]) {
      return;
    }
    this.events[name].forEach((item) => {
      item.apply(this, args);
    });
  }

  /**
   * 删除
   * @param {事件队列名} args
   */
  remove(name) {
    if (this.events[name]) {
      delete this.events[name];
    }
  }
}

const bus = new EventBus();

// 不同租客订阅了不同需求房型
bus.on("bigHouse", function (value) {
  console.log(`A收到了一条消息:${value}`);
});

bus.on("mediumHouse", function (value) {
  console.log(`B收到了一条消息:${value}`);
});

bus.on("smallHouse", function (value) {
  console.log(`C收到了一条消息:${value}`);
});

// 某天房东通过中介发布了一条消息
bus.emit("bigHouse", "别墅有房了"); // A收到了一条消息:别墅有房了
// 又某一天
bus.emit("mediumHouse", "洋房有房了"); // B收到了一条消息:洋房有房了
// 再某一天。。。。
bus.emit("smallHouse", "小平层有房了"); // C收到了一条消息:小平层有房了

回顾一下,从这个例子就可可以看到:

4、小结

参考学习:
https://juejin.im/post/5a14e9edf265da4312808d86
https://molunerfinn.com/observer-vs-pubsub-pattern
https://juejin.im/post/5bb1bb616fb9a05d2b6dccfa
https://juejin.im/post/57de12355bbb50005e648bd8

上一篇 下一篇

猜你喜欢

热点阅读