发布订阅和观察者模式的区别

有些人认为观察者模式就是发布订阅模式,实际上观察者模式是包含了订阅发布模式,发布订阅模式只是观察者模式中的一种。观察者模式是观察者和被观察者之间的通信,而发布订阅模式中间增加了一个中转层,通过第三方来分发信息。

 

观察者模式

    // Subject为被观察者,Subject中的状态(state)改变,就通知 Observer更新
    class Subject {
      constructor() {
        this.observes = []
        this.state = false
      }
      // this.observes存储观察者
      attach(observe){
        this.observes.push(observe)
      }
      // 状态改变,通知 Observer 触发更新
      setState(newState){
        this.state = newState
        this.observes.forEach( observer => observer.update(newState))
      }
    }
    // Observer为观察者,观察Subject的状态是否改变
    class Observer {
      constructor(name) {
        this.name = name
      }
      // 更新
      update(state){
        console.log(this.name + ",接收到了通知,被观察者的属性变为 " + state)
      }
    }
    var sub = new Subject()
    var obs1 = new Observer('观察者1')
    var obs2 = new Observer('观察者2')
    sub.attach(obs1)
    sub.attach(obs2)
    // 被观察者的状态改变,触发观察者更新
    sub.setState(true) 

vue中数据劫持中就用到了观察者模式,data中的属性一发生变化,就通知view界面更新,从而实现数据驱动,想要进一步了解vue底层原理,可以参考可以参考github上的一篇文章  MVVM实现

电脑刺绣绣花厂 http://www.szhdn.com 广州品牌设计公司https://www.houdianzi.com

发布订阅模式

 // 发布订阅
    class Events {
      constructor() {
        this.sub = {} // 容器
      }
      // 根绝不同 name,订阅对应函数
      $on(name, fn) {
        const wrap = this.sub[name] || (this.sub[name] = [])
        wrap.push(fn)
      }
      // 遍历所有相同name的订阅函数,并发布
      $emit(name, ...args) {
        const fns = this.sub[name] || []
        fns.forEach(fn => {
          fn.apply(this, args)
        })
      }
      // 销毁,避免内存泄漏
      $of(name){
        this.sub[name] = null
      }
    }
    // event 相当于中转器
    const event = new Events()
    // 订阅
    event.$on('eventname', function (a, b) {
      console.log(a, b)
    })
    event.$on('eventname', function (a, b) {
      console.log(a, b)
    })
    // 发布
    event.$emit('eventname', 'a', 'b')

vue中的兄弟组件通信bus的原理就是发布订阅模式,该模式有个缺点,当你订阅一个消息后,也许此消息最后都未发生,但这个订阅者会始终存在于内存中。所以该消息不使用的时候,调用$of销毁,以避免内存泄漏。

原文地址:https://www.cnblogs.com/qianxiaox/p/13821943.html