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


    观察者模式

    当对象之间存在一对多的依赖关系时,其中一个对象的状态发生改变,所有依赖它的对象都会收到通知,这就是观察者模式。

    在观察者模式中,只有两种主体:目标对象 (Subject) 和 观察者 (Observer)。

    • 目标对象 Subject:

      • 维护观察者列表 observerList ———— 维护拥有订阅权限的用户列表
      • 定义添加观察者的方法 ———— 提供用户订阅权限的功能
      • 当自身发生变化后,通过调用自己的 notify 方法依次通知每个观察者执行 update 方法 ———— 发布对应任务后通知有订阅权限的用户
    • 观察者 Observer 需要实现 update 方法,供目标对象调用。update方法中可以执行自定义的业务逻辑 ———— 定义接收任务通知后的方法。

    观察者模式

    class Subject {
      constructor() {
          this.observerList = [];
      }
    
      add(observer) {
          this.observerList.push(observer);
      }
      
      remove(observer) {
          this.observerList = this.observerList.filter(item => item !== observer)
      }
    
      notify(...args) {
          this.observers.forEach(observer => observer.update(...args));
      }
    }
    
    // 观察者
    class Observer {
      update(...args) {
          console.log(...args);
      }
    }
    
    // 创建观察者ob1
    let ob1 = new Observer();
    // 创建观察者ob2
    let ob2 = new Observer();
    // 创建目标sub
    let sub = new Subject();
    // 目标sub添加观察者ob1 (目标和观察者建立了依赖关系)
    sub.add(ob1);
    // 目标sub添加观察者ob2
    sub.add(ob2);
    // 目标sub触发SMS事件(目标主动通知观察者)
    sub.notify('I fired `SMS` event', 'heelp');
    

    发布订阅者模式

    基于一个事件(主题)PubSub 通道,希望订阅者 subscriber 通过自定义事件 subscribe 订阅主题。发布者publisher 通过 publish 发布主题事件的方式通知各个订阅该主题的 Subscriber 对象。

    因此发布订阅模式与观察者模式相比,发布订阅模式中有三个角色,发布者 Publisher ,事件调度中心 Event Channel ,订阅者 Subscriber

    上面的文字有些难以理解,在现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为调度中心或事件通道,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。

    • 任务发布者 —— Publisher

    • 事件中心 —— PubSub

      • 维护任务类型 subscribers 对象,以及每种任务下的订阅情况
      • 给订阅者提供订阅功能 —— subscribe 功能
      • 给发布者的提供发布任务 —— publish 功能
    • 订阅者 —— Subscriber

    举一个例子,你在微博上关注了A,同时其他很多人也关注了A,那么当A发布动态的时候,微博就会为你们推送这条动态。A就是发布者,你是订阅者,微博就是调度中心,你和A是没有直接的消息往来的,全是通过微博来协调的(你的关注,A的发布动态)。

    发布订阅模式

    class PubSub {
      constructor() {
          this.subscribers = {};
      }
       
      // 订阅
      subsctibe(topic, cb) {
        if (!this.subscribers[topic]) {
          this.subscribers[topic] = []
        }
        this.subscribers[topic].push(cb)
      }
      
      // 取消订阅
      unsubsctibe(topic, cb) {
        let temp = this.subscribers[topic]
        if (temp) {
          let index = temp.findIndex(item => item === cb)
          temp.splice(index, 1)
        }
      }
    
      // 发布功能
      publish(topic, ...args) {
        if (this.subscribers[topic]) {
          this.subscribers[topic].forEach(cb => cb(...args))
        }
      }
    }
    
    let clg = function(text) {
      console.log(text)
    }
    
    // 创建事件调度中心,为订阅者和发布者提供调度服务
    let pubSub = new PubSub();
    // A订阅了SMS事件(A只关注SMS本身,而不关心谁发布这个事件)
    pubSub.subscribe('SMS', clg);
    // B订阅了SMS事件
    pubSub.subscribe('SMS', clg);
    console.log(pubSub.subscribers)
    // C发布了SMS事件(C只关注SMS本身,不关心谁订阅了这个事件)
    pubSub.publish('SMS', 'I published `SMS` event');
    

    从代码实现可以看出,观察者模式则是面向目标和观察者编程的,而发布-订阅模式是面向调度中心编程的,前者用于耦合目标和观察者,后者用于解耦发布者和订阅者,不可同日而语也~

  • 相关阅读:
    python SO3 & so3 BCH近似计算
    Golang之封装Mysql Slave小例子
    智慧电力运维系统助力实现配电室无人值守
    linux的文件系统
    els 方块停在方块上。
    (附源码)ssm人才市场招聘信息系统 毕业设计 271621
    腾讯云服务器CVM_云主机_云计算服务器_弹性云服务器
    不同类型的软件测试
    谷粒商城 高级篇 (九) --------- 缓存失效问题
    [附源码]计算机毕业设计JAVAjsp校园志愿者服务管理系统
  • 原文地址:https://blog.csdn.net/qq_45934504/article/details/126964060