发布订阅/观察者模式-真正对比区别

364 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

引言

发布订阅与观察者模式是js设计模式里的一种,也是很常见,使用率极高的一种设计模式。在vue.js中这两种设计模式也是它的一个核心。
此文先讲解使用原理,并手动实现,在总结区别

发布订阅模式

分三个核心点:

  • 订阅者
  • 发布者
  • 信号中心/事件中心

发布订阅模式有一个统一的信号中心,由订阅者向里面投递自己的信号,当需要执行任务时,发布者就会向信号中心的每一个信息发送通知,然后各自开始执行自己的任务。发布者不用管信号中心有没有信号,信号是谁
通俗理解就是,订阅者(用户)下单买东西,发布者(老板)生产货物后,就看有没有订单,有订单就发送
代码实现:

// 事件触发器
class EventEmitter{
    // 构造函数创建信息中心
    constructor(){
      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(f => f())
      }
    }
}

var em = new EventEmitter()

// 订阅者注册信息事件
em.$on('click',() => console.log('click1'))
em.$on('click',() => console.log('click2'))

// 发布者执行信息事件
em.$emit('click')

执行结果,打印出click1 和 click2

观察者模式

分两个核心点:

  • 观察者 -- watcher对象
    包含update方法:当事件发生时,具体要做的事情
  • 发布器 -- dep
    包含subs数组:存储所有的观察者
    包含addSub方法:用于添加观察者
    包含notify方法:当事件触发时,调用所有观察者的update方法

注意:没有信号中心
观察者模式是没有一个统一的调度中心,观察者需要直接将自己注册到发布器中去,一旦事件触发,发布器就会挨个执行每个watcher观察者对象里的update方法,达到通知的效果
代码实现:

// 发布器
class Dep{
  constructor(){
    this.subs = []  // 记录所有的观察者
  }
  // 添加观察者
  addSub(sub){
    // 判断存在并且必须有update方法
    if(sub && sub.update){
      this.subs.push(sub)
    }
  }
  // 发布通知 挨个执行每个观察者的update方法
  notify(){
    this.subs.forEach(sub => sub.update())
  }
}
// 观察者
class Watcher{
  update(){
    console.log('update')
  }
}

var dep = new Dep()
var watcher = new Watcher()

dep.addSub(watcher)
dep.notify()

执行结果,打印出:update

总结

区别:
发布/订阅模式 有统一调度中心调用,因此发布者和订阅者不需要知道对方的存在
观察者模式 是由具体的发布器调度,比如当事件触发,Dep 就会去调用观察者的方法,所以观察者模 式的观察者与发布器之间是存在依赖关系的

20220607170406.jpg

往期精彩文章

🌟webpack 手写插件流程
🌟两种方式轻松做react css样式隔离
🌟彻底理解redux的中间件原理
🌟canvas实现刮刮奖效果
🌟前端实现pdf下载
🌟web前端性能优化(全汇总)
🌟一句话概括this指向问题
🌟MutationObserver 实现微任务原理分析
🌟遇到几次的大厂笔试题:装饰数组push方法
🌟V8垃圾回收策略与GC算法
🌟浏览器缓存策略(强缓存和协商缓存)
🌟$nextTick 源码解读与原理分析
🌟手动封装适合react hook使用的状态管理工具