发布订阅模式
一、什么是发布-订阅模式
发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
二、实现发布-订阅模式
1. 实现思路
- 创建一个对象
- 在对象上创建一个缓存列表(调度中心)
on方法把函数fn都加到缓存列表中(订阅者注册事件到调度中心)emit方法取到arguments里第一个当做event,根据event值去执行对应缓存列表中的函数(发布者发布事件到调度中心,调度中心处理代码)off方法根据event值取消订阅(取消订阅)once方法只监听一次,调用完毕后删除缓存函数(订阅一次)
2. demo1
//公众号对象
let eventEmitter = {};
//缓存列表,存放event及fn
eventEmitter.list = {};
//订阅
eventEmitter.on = function (event, fn) {
let _this = this;
//如果对象中没有对应event的值,说明没有订阅过,给event创建缓存列表
//如果有队形的event值,添加fn到对应event缓存列表里
(_this.list[event] || (_this.list[event] = [])).push(fn);
return _this;
};
//发布
eventEmitter.emit = function() {
let _this = this;
// 第一个参数是对应的 event 值,直接用数组的 shift 方法取出
let event = [].shift.call(arguments),
fns = [..._this.list[event]];
//如果缓存列表里没有fn就返回false
if (!fns || fns.length === 0) {
return false;
}
//遍历event值对应的缓存列表,依次执行fn
fns.forEach(fn => {
fn.apply(_this, arguments);
});
return _this;
};
function user1 (content) {
console.log('用户1订阅了:', content);
};
function user2 (content) {
console.log('用户2订阅了:', content);
};
// 订阅
eventEmitter.on('article', user1);
eventEmitter.on('article', user2);
// 发布
eventEmitter.emit('article', 'Javascript 发布-订阅模式');
/*
用户1订阅了: Javascript 发布-订阅模式
用户2订阅了: Javascript 发布-订阅模式
*/
三、观察者模式与发布订阅模式区别
-
观察者模式:一个对象(称为subject)维持一系列依赖于它的对象(称为observer),将有关状态的任何变更自动通知给它们(观察者)。
-
发布/订阅模式:基于一个主题/事件通道,希望接收通知的对象(称为subscriber)通过自定义事件订阅主题,被激活事件的对象(称为publisher)通过发布主题事件的方式被通知。
两种模式之间的差异
-
Observer模式要求观察者必须订阅内容改变的事件,定义了一个一对多的依赖关系;
-
Publish/Subscribe模式使用了一个主题/事件通道,这个通道介于订阅着与发布者之间;
-
观察者模式里面观察者「被迫」执行内容改变事件(subject内容事件);发布/订阅模式中,订阅者可以自定义事件处理程序;
-
观察者模式两个对象之间有很强的依赖关系;发布/订阅模式两个对象之间的耦合度低。