本文已参与「新人创作礼」活动,一起开启掘金创作之路。
发布订阅模式是什么?
定义
发布/订阅模式(Publish Subscribe Pattern)属于设计模式中的行为(Behavioral Patterns)。
发布-订阅模式其实是定义对象之间的一种 一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。这点和观察者模式十分的相似,但是又有着不同的地方,之后再来说说他们的不同。
订阅者把自己想订阅的事件注册到调度中心,当发布者发布该事件到调度中心,也就是该事件触发时,由调度中心统一调度订阅者注册到调度中心的处理代码
示例
就拿离我们最近的淘宝来做一个例子,商家们就是发布者,我们就是订阅者,淘宝就是这个调度中心。当我们关注了某一个店铺或者商品,我们就算是把自己想要关心的事注册到了调度中心,也就是利用淘宝关注了某个店铺或者商品,然后当这个店铺或者商品发布了自己的事件,调度中心就会对所有注册的订阅者做一个通知,也就是如果商家或者商品做出了降价啊之类的活动,那么他只需要把消息通知给淘宝,淘宝会把降价的消息发送给每一个关注了的人。
发布订阅模式有什么用?
解决了一个对象方式改变其他对象通知的问题
才前面举的例子来理解这句话,就是你想要关注某个事件,比如降价,就把这件事注册给淘宝,然后就不需要再去进行多余的操作,只需要等商家发布消息,商家一发布消息,你就能做出对应的操作。这样就能给对象之间相互调用带来极大的便利
发布订阅模式的优点?
- 松耦合:
发布/订阅者模式可以降低通信对象之间的耦合度,发布者不需要去关心订阅者是谁,订阅者也不需要去关心发布者怎样发布,发布者只管把事件交给调度中心,订阅者只管在收到通知的时候做出对应的响应。这样即使没有订阅者或者订阅者取消订阅,并不会影响整体的运行。 - 可靠性:
发布/订阅者模式提高了可靠性。异步的消息传递有助于我们的系统哪怕在高负载下继续平稳运行。
发布订阅模式的缺点?
-
就如同优点所说,将两个对象解耦不仅是他的优点,也是它的缺点所在:
-
一个系统当中如果存在了太多的发布事件,会导致维护的时候困难大大提升,因为过多的事件需要花费大量的时间去一一辨别。
实际使用
首先要先根据发布订阅中三个角色的功能来分析一下每个角色中应该含有什么方法:
-
发布者:发布者需要发布事件,并且在特定的情况可以传参数给订阅者
-
订阅者:需要注册自己感兴趣的事件并且定义在这个事件触发的时候要执行的函数
-
调度中心:定义一个列表来存放事件以及事件对应的方法,还要有定义emit( 发布事件 ),on( 订阅事件 ),还有扩展出去的功能:订阅就要有取消订阅--off( 取消订阅方法 )以及只订阅一次--once( 单次订阅 )
let corp = {};
// 调度中心
corp.list = {};
corp.on = function (key, fn) {
// 如果对象中没有对应的key值
// 也就是说明没有订阅过
// 那就给key创建个缓存列表
if (!this.list[key]) {
this.list[key] = [];
}
// 把函数添加到对应key的缓存列表里
this.list[key].push(fn);
};
corp.emit = function () {
// 第一个参数是对应的key值
// 直接用数组的shift方法取出
let key = [].shift.call(arguments),
fns = this.list[key];
// 如果缓存列表里没有函数就返回false
if (!fns || fns.length === 0) {
return false;
}
// 遍历key值对应的缓存列表
// 依次执行函数的方法
fns.forEach((fn) => {
fn.apply(this, arguments);
});
};
// 测试用例
corp.on("join", (position, salary) => {
console.log("你的职位是:" + position);
console.log("期望薪水:" + salary);
});
corp.on("other", (skill, hobby) => {
console.log("你的技能有: " + skill);
console.log("爱好: " + hobby);
});
corp.emit("join", "前端", 10000);
corp.emit("join", "后端", 10000);
corp.emit("other", "端茶和倒水", "足球");
/*
你的职位是:前端
期望薪水:10000
你的职位是:后端
期望薪水:10000
你的技能有: 端茶和倒水
爱好: 足球
*/
通过这个例子就能够大概了解发布订阅模式,一般来说,看到 on emit 一类的关键词,就能够认定使用了发布订阅模式,那么接下来关键的就是去查看订阅的事件以及传递的参数。这是在阅读代码时候要注意的一个点。
总结
发布订阅模式能够给大部分的对象之间的消息通知带来极大的便利,并且降低他们之间的耦合度,但是还是要注意不能够过度的时候发布订阅模式,就像上文所说,过度的使用可能会给后期的维护带来不必要的麻烦。
引用外部文章: