定义
Define a one-to-many dependency between objects so that when one object change state,all its dependents are notified and updated automatically.
(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新)
实现代码
//具体的观察者
class Observer {
public update(info:any){
//...some code
console.log(`收到${info},更新`);
}
}
//具体的被观察者
class Subject {
private observerList = new Array<Observer>();
public addObserver(obs:Observer){
this.observerList.push(obs);
}
public deleteObserver(obs:Observer){
let index = this.observerList.findIndex((val)=>{
return val===obs;
});
index>-1&&this.observerList.splice(index,1);
}
public notify(info:any){
for (const obs of this.observerList) {
try {
obs.update(info);
} catch (error) {
console.error(error);
}
}
}
}
与事件总线的区别
事件总线是基于事件进行发布/订阅的,是多对多,存在中间者管理事件队列,发布者和订阅者解耦。前端最常见的点击事件监听就是如此设计。
观察者模式是基于对象进行发布/订阅的,是一对多,观察者和被观察者松耦合。
事件总线的实现
class EventBus{
private eventList:{
[prop: string]: Function[]
} = {};
public addEventListener(eventName:string,lis:Function){
const thisEvent = this.eventList[eventName]||[];
thisEvent.push(lis);
this.eventList[eventName] = thisEvent;
}
public removeEventListener(eventName,lis:Function){
const thisEvent = this.eventList[eventName];
if(thisEvent){
let index = thisEvent.findIndex((val)=>{
return val===lis;
});
index>-1&&thisEvent.splice(index,1);
}
}
//真正的发布者通过这个方法通知订阅者
public needUpdate(eventName:string,info:any){
const thisEvent = this.eventList[eventName];
if(thisEvent){
for (const lis of thisEvent) {
lis.call(this,info);
}
}
}
}
应用场景的区别
它们都常作触发(通信)机制,比如说被观察者类状态变了,通知观察者重新计算更新自己。
观察者模式一对多,比较专注,一般用于独立的局部通信,比如架构中单层或单应用内部通信。也可以用消息队列把多个联合起来,可以看下Vue的数据双向绑定的实现。
事件总线可多对多,比较灵活方便,一般作用于多种事件的全局通信,比如DOM事件监听、跨服务通信。
区别没有那么大,观察者模式比较独立,用消息队列把多个联合起来,就有了中间层,就很像事件总线了。
【参考文章】