概念
发布订阅者模式,是javascript甚至大多数语言都有的语言模式,比较概念的解释是,
订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布该事件到调度中心(第三方),由调度中心统一调度订阅者注册到调度中心的处理代码。
优缺点
优点
1.一对多。
一个发布者可以绑定多个订阅者,当事件触发时,由调度中心全部通知。
2.解耦。
发布订阅者模式中,订阅者是不知道也不关心事件是为什么触发,是由哪一个事件触发,只知道事件触发时候,会告诉自己。发布者也不用一一通知,只要告诉调度中心,事件触发了就好了。所以代码松耦合。
3.程序便于扩展。
缺点:
实现方式麻烦?
举例
用平时身边的例子解释,比如你被阿里邀请面试,面试完你问面试官什么时候出结果,面试官告诉你结果出来时候会通知你的,这样你就不用天天打电话问面试结果了,等面试结果出来,面试官会把面试结果统一发邮件给面试者,当你收到面试结果后,进行下一步操作,是到阿里上班,还是面试下一家。
代码实现
var observer = function () {
var _observer = {};
let _queue = {}; // 所有事件的队列
/**
* @param 注册的事件名称
* @param 事件触发时执行的函数
*/
_observer.on = function (eventName, fn) {
if (Object.prototype.toString.call(fn) !== ‘[object Function]‘) return;
if (_queue[eventName] && _queue[eventName].length > 0) {
// 如果之前注册过eventName事件
_queue[eventName].push(fn);
} else {
// 之前没有注册过eventName事件
_queue[eventName] = [fn];
}
},
/**
* @param 已经触发的事件(发布事件)
*/
_observer.trigger = function (triggerEventName) {
var args = Array.prototype.slice.call(arguments,1);
if (!_queue[triggerEventName]) return;
for (var i = 0; i < _queue[triggerEventName].length; i++) {
_queue[triggerEventName][i].apply(null, args);
}
},
// 移除注册事件
_observer.remove = function (removeEventName) {
for(var k in _queue) {
if (k === removeEventName) {
delete _queue[k];
}
}
}
// 移除所有注册事件
_observer.removeAll = function () {
_queue = {};
}
return _observer;
}()
发布订阅者模式与观察者模式区别
发布订阅者模式与观察者模式是很相似的,之前的好多网站、博客上也把它们画上等号,但是我前段时间接到一个面试,问我,发布订阅者模式与观察者模式有什么却别,当时说一样的,结果面试管说其实不一样,好吧,一脸懵逼,结束时候自己查阅了一下,确实不太一样。
区别
- 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过调度中心进行通信。
- 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
- 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)
举个例子
观察者模式就像你没有经验却买了比特币或者股票,然后害怕赔钱一直盯着k线图,一有变化立马就知道了,然后做下一步操作,是观望是买是抛都可以,熟悉vue的同学应该知道watch这个方法吧,对,就是观察者模式,国外有一图拿过来给你们看看