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

        发布订阅模式通常又被称为消息机制,它定义了对象间的一种一对多的依赖关系,只要当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,解决了主体对象与观察者之间功能的耦合,即一个对象状态改变给其他对象通知的问题,常用于组件间通信。

js是监听HistoryRouter的变化 

class Dep {                  // 订阅池
    constructor(name){
        this.id = new Date() //这里简单的运用时间戳做订阅池的ID
        this.subs = []       //该事件下被订阅对象的集合
    }
    defined(){              // 添加订阅者
        Dep.watch.add(this);
    }
    notify() {              //通知订阅者有变化
        this.subs.forEach((e, i) => {
            if(typeof e.update === 'function'){
                try {
                   e.update.apply(e)  //触发订阅者更新函数
                } catch(err){
                    console.warr(err)
                }
            }
        })
    }
}
Dep.watch = null;
class Watch {
    constructor(name, fn){
        this.name = name;       //订阅消息的名称
        this.id = new Date();   //这里简单的运用时间戳做订阅者的ID
        this.callBack = fn;     //订阅消息发送改变时->订阅者执行的回调函数     
    }
    add(dep) {                  //将订阅者放入dep订阅池
       dep.subs.push(this);
    }
    update() {                  //将订阅者更新方法
        var cb = this.callBack; //赋值为了不改变函数内调用的this
        cb(this.name);         
    }
}

手写发布订阅

  • 需要有一个map对象缓存订阅事件
  • 订阅(on)如果存在事件就往list里面缓存事件
  • 取消订阅(off)从list对象找到订阅事件删除
  • 发布(emit)从list对象找到事件去执行就OK
  • 只发布一次(once)执行完删除即可
class EventEmitter{
  constructor() {
    this.map = {} 
  }
    // 订阅
  on(type, handler) {
    this.map[type] = (this.map[type] || []).concat(handler)
  }

    // 取消订阅
  off(type, handler) {
    if(this.map[type]) {
      if(!this.map[type].length) {
        delete this.map[type]
      } else {
        let index = this.map[type].indexOf(handler)
        this.map[type].splice(index, 1)
      }
    }
  }
    // 发布
  emit(type, data) {
    this.map[type] && this.map[type].forEach(handler => handler(data))
  }
    // 执行一次
  once(type, handler) {
    let fn = (...args) => {
      handler.apply(this, args);
      this.off(type, handler);
    };
    this.on(type, fn);
  }
}


// 测试
let eventEmitter= new EventEmitter()

eventEmitter.on('click', data => {
  console.log(data)
})

eventEmitter.fire('click', {a: 3})//{ a: 3}
eventEmitter.off('click')//销毁后,无结果
eventEmitter.fire('click', {b: 2})//无返回

eventEmitter.once('click', data => {
  console.log(data);
})
 

观察者模式 

 发布订阅模式除了有发布者和订阅者,还有中间商

而类似的 观察者模式 只有观察者和消费者:

let observer_ids=0;
let observed_ids=0;
//观察者类
class Observer {
   constructor() {
      this.id = observer_ids++;
   }
   //观测到变化后的处理
   update(ob){
      console.log("观察者" + this.id + `-检测到被观察者${ob.id}变化`);
   }
}
//被观察者列
class Observed {
   constructor() {
      this.observers = [];
      this.id=observed_ids++;
   }
   //添加观察者
   addObserver(observer) {
      this.observers.push(observer);
   }
   //删除观察者
   removeObserver(observer) {
      this.observers = this.observers.filter(o => {
         return o.id != observer.id;
      });
   }
   //通知所有的观察者
   notify(ob) {
      this.observers.forEach(observer => {
         observer.update(ob);
      });
   }
}

let mObserved=new Observed();
let mObserver1=new Observer();
let mObserver2=new Observer();

mObserved.addObserver(mObserver1);
mObserved.addObserver(mObserver2);

mObserved.notify();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白目

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值