发布订阅
发布订阅模式需要两个方法,发布和订阅,发布和订阅是完全解耦的。
// 事件注册后可以手动触发去执行回调的一种思想
// @1 发布者模式维护的是一个回调函数列表
let event = {
_arr: [],
on(key, fn) {
this._arr.push({ key, fn });
},
emit(key, data) {
var curCb = this._arr.find(itm => itm.key == key).fn; // 找到对应的回调
curCb && curCb(data);
}
}
event.on('first', data => {
console.log(`${ data }`);
});
event.on('second', data => {
console.log(`${ data }`);
});
event.emit('first', '发送第一个数据');
event.emit('second', '发送第二个数据');
// 发送第一个数据
// 发送第二个数据
观察者模式
观察者模式是基于发布订阅的,而且观察者模式是基于类来实现的,当订阅的事件状态发生改变,会自动通知观察者,实现回调方法立即执行。
// 观察者模式需要两个类 观察者和被观察者
// @1 观察者模式维护的是一个观察者列表,它的回调在原型上「update」
class Subs { // 被观察者
constructor(name) {
this.name = name;
this.watchers = []; // 观察者列表 而不是事件列表啦
this.state = '开心😊';
}
attach(watcher) {
this.watchers.push(watcher);
}
setState(newState) { // 改变被观察者状态
this.state = newState;
// 自动执行观察者的回调方法
this.watchers.forEach(wacher => wacher.update(newState));
}
}
class Observer{ // 观察者
constructor(name) {
this.name = name;
}
update(state) { // 被观察者状态变化了,需要更新啦
console.log(`${ this.name }知道啦: 当前宝宝状态是 ${ state }`);
}
}
var baby = new Subs('宝宝');
var o1 = new Observer('爸爸');
var o2 = new Observer('妈妈');
baby.attach(o1);
baby.attach(o2);
baby.setState('不开心😣');
// 爸爸知道啦: 当前宝宝状态是 不开心😣
// 妈妈知道啦: 当前宝宝状态是 不开心😣
二者之间的区别
- 发布订阅模式维护了一个回调函数的列表,每次触发执行该函数,而观察者模式维护了一个观察者列表,每次触发去调用观察者继承自类的 update 方法。
- 发布订阅是手动触发回调,观察者模式只要被观察者状态变化,则主动通知观察者去执行回调。