04- 发布订阅模式和观察者模式

301 阅读1分钟

发布/订阅 模式

  • 发布/订阅模式
    • 订阅者

    • 发布者

    • 信号中心

      我们假定存在一个“信号中心”,某个任务执行完成,就向信号中心“发布(publish)”一个信号, 其他任务可以向信号中心 “订阅(subscribe)” 这个信号, 从而知道什么时候自己可以执行, 这就叫“发布/订阅模式(publish- subscribe- pettern)

自定义实现 vue 中的发布订阅模式。

   // 事件触发器
  class EventEmitter {
   constructor () {
    //  {'click': [fn1,fn2], 'change': [fn]}
     this.subs = Object.create(null)
   }
   
    // 注册事件
    $on(eventType, handler) {
      this.subs[eventType] = this.subs[eventType] || []
      this.subs [eventType].push(handler)
    }
    // 触发事件
    $emit(eventType) {
      if(this.subs[eventType]){
        this.subs[eventType].forEach(handler => {
          handler()
        })
      }
    }
  }

  // 测试
  let em = new EventEmitter()
    em.$on('click', ()=>{
      console.log('click1')
    })

    em.$on('click', ()=>{
      console.log('click2')
    })
    
    em.$emit('click')

观察者模式

  • 观察者(订阅者) - watcher
    • update(): 当事件发生时,具体要做的事情
  • 目标(发布者) - Dep
    • subs数组: 储存所有的观察者
    • addSub(): 添加观察者
    • notify(): 当事件发生, 调用所有观察者的 update() 方法

实现观察者模式

   //  发布者-目标
  class Dep {
    constructor () {
      // 记录所有的订阅者
      this.subs = []
    }
    // 添加观察者
    addSub (sub) {
      if(sub && sub.update) {
        this.subs.push(sub)
      }
    }
    // 发布通知
    notify () {
       this.subs.forEach(sub => {
         sub.update()
       })
    }
  }
  // 订阅者-观察者
  class Watcher {
    update(){
      console.log('update')
    }
  }

  let dep  = new Dep()
  let watcher = new Watcher()
  dep.addSub(watcher)
  dep.notify()

总结

  • 观察者模式是由具体目标调用, 比如当事件触发, Dep 就会去调用观察者的方法, 所以观察者模式的订阅者与发布者之间是存在依赖的

  • 发布/订阅模式由统一调度中心调用, 因此发布者和订阅者不需要知道对方的存在

image.png