JS设计模式 之 发布-订阅模式
1、什么是发布-订阅模式
发布-订阅模式是属于经过解耦合的观察者模式。
让多个订阅者对象同时监听某一个调度中心,这个调度中心观察到发布者发生变化的时候,会通知所有的订阅者。
涉及的几个角色:
- 订阅者:收到通知之后,可以更新自己
- 调度中心:通知订阅者
- 发布者:被调度中心监视
比如说我们上淘宝买一样东西,但是价格有点贵,所以我们可以把它加入淘宝的降价通知功能中去,这样子,当商家降低该商品的价格的时候,我们就能够收到对应的淘宝发出的通知。
这时候,淘宝就是一个调度中心,我们买家就是订阅者,卖家就是发布者。
2、发布-订阅模式有什么用?
解决了一个对象方式改变其他对象通知的问题,解耦他们之间的依赖关系。
你要买某样东西,你不需要在一直去关注物品的价格是否降低,会由淘宝来通知你,你只需要等待淘宝的信息,这样就实现了你和商家之间的解耦,你都不需要去知道商家的商品是涨价了还是降价了,反正当它一降价,淘宝就去通知你。
如图所示:
3、发布-订阅模式的优点与缺点
优点:
- 解耦。像上方提到过的,通过发布订阅模式进行通信,通信双方不需要有任何的联系,只需要关注彼此的事件即可。
- 广泛应用于异步编程当中。在异步编程中,我们是不知道结果什么时候会返回的,通常的办法就是通过传入一个回调函数,在异步结束后,调用这个回调函数,有值的话就将值作为回调的参数传入。但是在发布订阅中,只需要在外部去订阅一个事件,比方说 'ready' 事件,那么在异步结束的时候,就可以发布 'ready' 这个事件,那么订阅方就会执行它订阅的函数,并且发布事件也是可以传递参数的。
缺点:
- 解耦,将两个对象解耦不仅是他的优点,也是它的缺点所在
- 因为发布者不会去关心事件发布的结果,所以一旦事件发布结束想要进行反馈就没有办法。
- 比方说上方的某个事件发布之后,订阅者做出了对应的操作,但是你没有办法通知发布者你执行了什么操作,你只能通过发布事件的方式在发一个事件回去。
4、发布-订阅模式代码实现
// 调度中心
class EventBus {
constructor() {
// 事件集
this.handles = {};
}
// 订阅事件
on(eventType, handle) {
if (!this.handles.hasOwnProperty(eventType)) {
this.handles[eventType] = [];
}
if (typeof handle == 'function') {
this.handles[eventType].push(handle);
} else {
throw new Error('缺少回调函数');
}
return this; // 实现链式操作
}
// 发布事件
emit(eventType, ...args) {
if (this.handles.hasOwnProperty(eventType)) {
this.handles[eventType].forEach((item, key, arr) => {
item.apply(null, args);
});
} else {
throw new Error(eventType + "事件未注册");
}
return this; // 实现链式操作
}
// 取消订阅
off(eventType, handle) {
if (!this.handles.hasOwnProperty(eventType)) {
throw new Error(eventType + "事件未注册");
} else {
this.handles[eventType].forEach((item, key, arr) => {
if (item == handle) {
arr.splice(key, 1);
}
});
}
return this; // 实现链式操作
}
}
let eventBus = new EventBus();
// 发布者
class Publisher {
constructor() {}
lowPrice(price) {
// 发布lowPrice事件
eventBus.emit('lowPrice', price);
}
}
// 订阅者
class Subscriber {
constructor() {}
lowPriceHandle(price) {
console.log("目前最低价是:" + price + "元");
}
getLowPrice() {
// 订阅lowPrice事件
eventBus.on('lowPrice', this.lowPriceHandle);
}
offLowPrice() {
eventBus.off('lowPrice', this.lowPriceHandle);
}
}
// 订阅者订阅了关于某个商品最新促销价的消息
const subscriber = new Subscriber();
subscriber.getLowPrice();
// 发布者发布了某个商品的最新促销价
const publisher = new Publisher();
publisher.lowPrice(100); // test.html:76 目前最低价是:100元
// 订阅者取消订阅
subscriber.offLowPrice();
publisher.lowPrice(200);
学习参考: