js观察者模式与发布订阅模式

in JavaScript with 0 comment

// 发布订阅模式与观察者模式的不同
//1 目标对象并不直接通知观察者,而是通过事件中心来派发通知。低解耦
//2 观察者模式大多数时候是同步的,比如当事件触发,Subject 就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。
//3 发布订阅模式,不是所有订阅都必须接受消息,可以选择性通知发布者
//4 观察者模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式

Vue中的响应式是使用了观察者模式,事件机制 ($on, $emit)则使用了发布订阅模式,同时Vue 的生命周期钩子也是是利用发布订阅模式实现的,另外Vue指令使用了装饰器模式

观察者模式

//有一个消息中心,信息接受者订阅某个信息,信息发布者发布消息后,订阅这个消息的所有订阅者都能收到信息
      class Subject {
        constructor() {
          // 消息中心
          this.observers = [];
        }
        //订阅消息
        subject(observer) {
          !this.observers.includes(observer) && this.observers.push(observer);
        }
        //发布消息
        notify() {
          this.observers.forEach(function (observer) {
            observer.show();
          });
        }
        //取消消息订阅
        remove(observer) {
          const idx = this.observers.findIndex((item) => item === observer);
          idx > -1 && this.observers.splice(idx, 1);
        }
      }
      class Observer {
        constructor(name, age) {
          this.name = name;
          this.age = age;
          //this.ob = new Observer();
        }
        show() {
          console.log("my name is " + this.name + " age is: " + this.age);
          //console.log("发布消息了");
        }
      }

      let sub = new Subject();
      let ob1 = new Observer("zong", 22);
      let ob2 = new Observer("dealdot", 32);
      sub.subject(ob1);
      sub.subject(ob2);
      sub.notify();

发布订阅模式

class PubSub {
        constructor() {
          // 保存监听事件
          this.event = {};
        }

        // 订阅
        subscribe(eventName, fun) {
          try {
            if (!this.event.hasOwnProperty(eventName)) {
              this.event[eventName] = [];
            }
            if (typeof fun == "function") {
              this.event[eventName].push(fun);
            } else {
              throw new Error(`请给${eventName}事件添加回调方法`);
            }
          } catch (error) {
            console.warn(error);
          }
        }

        // 发布
        publish(eventName, arg) {
          try {
            if (this.event.hasOwnProperty(eventName)) {
              this.event[eventName].map((item) => {
                item.call(null, arg);
              });
            } else {
              throw new Error(`${eventName}事件未被注册`);
            }
          } catch (error) {
            console.warn(error);
          }
        }

        // 移除订阅
        unSubscribe(eventName, fun, arg) {
          try {
            if (this.event.hasOwnProperty(eventName)) {
              this.event[eventName].map((item, index) => {
                if (item == fun) {
                  this.event[eventName].splice(index, 1);
                  item.call(null, arg);
                }
              });
            }
          } catch (error) {
            console.warn(error);
          }
        }
      }

      // 实例化
      const util = new PubSub();

      function notice1(params) {
        console.log(params);
      }
      function notice2(params) {
        console.log(params);
      }
      // 订阅事件
      util.subscribe("subscribe1", notice1);
      util.subscribe("subscribe2", notice2);

      // 发布事件
      //发布者可以选择要通知的订阅者对象[与观察者模式的不同]
      util.publish("subscribe1", "订阅成功");

      // 移除订阅
      setTimeout(() => {
        util.unSubscribe("subscribe1", notice, "已取消订阅");
      }, 3000);
评论已关闭.