带你轻松搞定观察者模式和发布订阅模式的区别

发布日期: 2022-05-07

浏览量: 3108

01、模式的概念

熟悉Vue的小伙伴都知道,在Vue中使用“观察者模式”去通知视图更新,使用“发布订阅”$on,$emit来实现自定义事件,所以搞清楚两者之间的关系很重要啦!

02、观察者模式

一个对象(观察者)订阅另一个对象(主题),当主题被激活的时候,触发观察者里面的事件。

举个例子:打点滴时,我们会观察吊瓶的变化,当快打完时,就要通知护士来取针。这里护士/我们就是观察者(Obeserver),吊瓶就是被观察者/主题。

  class Subject { //被观察者数据--吊瓶

    constructor(name="蛋糕老师"){

    this.state = 100;

    this.name = name;

    this.obs = [] //会有多个观察者

    }

      addObs(ob){

        this.obs.push(ob)

          }

  setState(state){ //改变状态的方法

    this.state = state

    //要去通知观察者去做动作 -- 拔针 

    this.obs.forEach((ob)=>{

      ob.update(this) //让观察者去做更新

        })

      }

}

  class Obeserver{ //观察者 -- 医生

    constructor(name){

    this.name = name;

  //在观察者里面是否可以记录/观察了哪些数据

         }

    update(subject){

    //医生也有可能观察多个打针的人 

    if (!subject.state) {

        console.log(`${this.name} 收到通知         :${subject.name} 的 带瓶打完啦!`)

        }else {

    console.log(` ${this.name} 收到通知 :${subject.name} 的带瓶量: ${subject.state}!`)

               }

         }

     }

     var zhiliao = new Subject();

     var hushi = new Obeserver("护士");

     var yisheng = new Obeserver("医生")

     zhiliao.addObs(hushi) 

     zhiliao.addObs(yisheng)

     zhiliao.setState(50) 

03、发布订阅

订阅者把自己想要订阅的事件注册到调度中心,当发布者发布事件到调度中心(就是该事件被触发),再由调度中心统一调度订阅者注册到调度中心的处理代码。

其实简单理解就是我们的自定义事件,比如在Vue中,Vue实例($bus)就是统一的调用中心,我们使用$bus去$on一个自定义事件myEvent就是发布者发布一个事件到调度中心,然后在其他地方$bus.$emit(myEvent)一下就相当于事件被触发,然后$bus就去执行对应事件的回调函数 。var Event = {

    _listeners: {},    

    // 添加

    $on: function(type, fn) {

if (typeof this._listeners[type] === "undefined") {

  this._listeners[type] = [];

        }

    if (typeof fn === "function") {

      this._listeners[type].push(fn);

      }    

     return this;

    },

    // 触发

  $emit: function(type) {

    var arrayEvent = this._listeners[type];

    if (arrayEvent instanceof Array) {

      for (var i=0, length=arrayEvent.length; i

        if (typeof arrayEvent[i] === "function") {

          arrayEvent[i]({ type: type });    

                }

            }

        }    

        return this;

    },

    // 删除

  $off: function(type, fn) {

    var arrayEvent = this._listeners[type];

    if (typeof type === "string" && arrayEvent instanceof Array) {

      if (typeof fn === "function") {

      for (var i=0, length=arrayEvent.length;i+=1){

      if (arrayEvent[i] === fn){

        this._listeners[type].splice(i, 1);

        break;

         }

         }

      } else {

        delete this._listeners[type];

            }

        }

        return this;

    }

};

04、总结

学习这两种模式,其实就是为了代码解耦 ,让每个独立的对象分开。需要从日常的业务场景去观察,比如在分页插件中,就可以利用“发布订阅”为点击每一个分页数的时候触发($emit)一个自定义事件,如果需要在点击分页的是做一些其他的时候,就可以在外面$on 这个事件,那么分页插件就可以很好的封装起来,不用给里面传递参数或者回调函数之类的了。


关注我们
值得信赖的IT教育机构

值得信赖的IT培训机构

成都校区地址:成都市武侯区孵化园9号楼A座2楼 西安校区地址:西安市未央区凤城九路海博广场B座 深圳校区地址:深圳市福田区彩田南路深圳青年大厦

蓉华教育,行胜于言,IT培训学校口碑选择

2016-2024 版权所有 © 成都蓉华软创科技有限公司官网(蜀ICP备20007585号-1 )

微信咨询

微信咨询

联系电话

联系方式

173-5852-6576