发布订阅模式与观察者模式
观察者模式
观察者模式定义
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。
观察者模式代码实现
/**
* 观察者观察的对象
*/
class Subject {
observers: Observer[];
constructor() {
this.observers = [];
}
// 添加观察者
add(observer: Observer) {
observer instanceof Observer && this.observers.push(observer);
}
// 移除观察者
remove(observer: Observer) {
if (observer instanceof Observer) {
const idx = this.observers.findIndex((i) => i === observer);
if (idx > -1) {
this.observers.splice(idx, 1);
return true;
}
}
return false;
}
// 通知观察者
notify() {
this.observers.forEach((ob) => {
ob.update();
});
}
}
/**
* 观察者
*/
class Observer {
name: string;
constructor(name: string) {
this.name = name;
}
// 观察的对象发生改变时对应的回调
update() {
console.log(
"this is call back of observer" + this.name + " when the observed subject changes"
);
}
}
const sub = new Subject();
const ob1 = new Observer("1");
const ob2 = new Observer("2");
const ob3 = new Observer("3");
sub.add(ob1);
sub.add(ob3);
sub.notify();
// this is call back of observer1 when the observed subject changes
// this is call back of observer3 when the observed subject changes
sub.remove(ob1);
sub.notify();
// this is call back of observer3 when the observed subject changes
发布订阅模式
发布订阅模式定义
发布-订阅模式其实是一种依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。订阅者把自己想订阅的事件注册到调度中心(Event Channel),当发布者发布该事件到调度中心,也就是该事件触发时,由调度中心统一调度订阅者注册到调度中心的处理代码。
发布订阅模式代码实现
class EventChannel {
eventList: Map<string, Function[]>;
constructor() {
this.eventList = new Map();
}
listen(action: string, fn: Function) {
const fns = this.eventList.get(action) || [];
fns.push(fn);
this.eventList.set(action, fns);
}
remove(action: string, fn: Function) {
const fns = this.eventList.get(action);
if (!fns) {
return false;
}
const idx = fns.findIndex((f) => f === fn);
if (idx > -1) {
fns.splice(idx, 1);
this.eventList.set(action, fns);
return true;
}
return false;
}
notify(action: string) {
const fns = this.eventList.get(action);
fns && fns.forEach((fn) => fn());
}
}
const evtChannel = new EventChannel();
function fnToBeRemoved () {
console.log('Cephass subscribes action1');
}
evtChannel.listen('action1', function() {
console.log('Mike subscribes action1');
})
evtChannel.listen('action1', fnToBeRemoved)
evtChannel.listen('action2', function() {
console.log('Garphy subscribes action2');
})
evtChannel.notify('action1');
// Mike subscribes action1
// Cephass subscribes action1
evtChannel.notify('action2');
// Garphy subscribes action2
evtChannel.remove('action1', fnToBeRemoved)
evtChannel.notify('action1');
// Mike subscribes action1
两者区别
订阅发布模式优点
- 发布者和订阅者是解耦的,只要引入订阅发布模式的事件中心,无论在何处都可以发布订阅。同时订阅发布者相互之间不影响。
订阅发布模式缺点
- 使用不当会造成数据流混乱,导致代码不好维护。
- 性能消耗更大,订阅发布模式需要维护事件列队,订阅的事件越多,内存消耗越大。
观察者模式优点
- 代码逻辑清晰,容易维护。
观察者模式缺点
- 相比订阅发布模式,目标和观察者是耦合在一起。