一、 定义
也称作发布-订阅模式,定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
二、 核心
取代对象之间硬编码的通知机制,一个对象不用再显式地调用另外一个对象的某个接口。
与传统的发布-订阅模式实现方式(将订阅者自身当成引用传入发布者)不同,在JS中通常使用注册回调函数的形式来订阅。
三、实现
JS中的事件就是经典的发布-订阅模式的实现。
// 订阅
document.body.addEventListener('click', function() {
console.log('click1');
}, false);
// 发布
document.body.click(); // click1
*实例:小明坐在后门口,可以很好的查看老师的巡逻情况。所以几个同学就让他帮忙看一下,如果老师来了就通知一声。
const observer = {
subscribes: [],
// 订阅
subscribe: function(cb) {
if (!cb) return;
if (this.subscribes.includes(cb)) return;
this.subscribes.push(cb)
console.log('有人订阅,总订阅数:', this.subscribes.length)
},
// 发布
publish: function (msg) {
this.subscribes.forEach(cb => {
cb(msg)
});
},
// 取消订阅
remove: function(cb) {
const index = this.subscribes.indexOf(cb);
if (index > -1) {
this.subscribes.splice(index, 1);
console.log('有人取消订阅,总订阅数:', this.subscribes.length)
}
}
}
// ==== 测试使用 ====
// 订阅者1 - 张三
const zsan = (msg) => {
console.log('---------zsan收到通知:', msg)
}
// 订阅者2 - 李四
const lisi = (msg) => {
console.log('---------lisi收到通知:', msg)
}
observer.subscribe(zsan)
observer.subscribe(lisi)
observer.publish.call(observer, '张老师来了')
// 张三要认真听课了,让小明不用再通知他了。
observer.remove(zsan)
observer.publish.call(observer, '他走了走了')
// 输出:
有人订阅,总订阅数: 1
有人订阅,总订阅数: 2
---------zsan收到通知: 张老师来了
---------lisi收到通知: 张老师来了
有人取消订阅,总订阅数: 1
---------lisi收到通知: 他走了走了
四、优缺点
优点
- 一为时间上的解耦,二为对象之间的解耦。可以用在异步编程中与MV*框架中
缺点
- 创建订阅者本身要消耗一定的时间和内存,订阅的处理函数不一定会被执行,驻留内存有性能开销;
- 弱化了对象之间的联系,复杂的情况下可能会导致程序难以跟踪维护和理解。