# 观察者模块 vs 发布订阅模式
观察者模式中主体和观察者是互相感知的,发布-订阅模式是借助第三方来实现调度的,发布者和订阅者之间互不感知。

有一种比喻:
- 发布-订阅模式就好像报社, 邮局和个人的关系,报纸的订阅和分发是由邮局来完成的。报社只负责将报纸发送给邮局。
- 观察者模式就好像 个体奶农和个人的关系。奶农负责统计有多少人订了产品,所以个人都会有一个相同拿牛奶的方法。奶农有新奶了就负责调用这个方法。
【发布-订阅模式】
class PubSub {
constructor() {
this.subscribers = []; // 全部订阅者
}
// 订阅
subscribe(topic, callback) {
let callbacks =this.subscribers[topic];
if(!callbacks) {
this.subscribers[topic] = [callback];
}else{
callbacks.push(callback);
}
}
// 发布
publish(topic, ...args) {
let callbacks =this.subscribers[topic] || [];
callbacks.forEach(callback => callback(...args));
}
}
// 创建事件调度中心,为订阅者和发布者提供调度服务
let pubSub =new PubSub();
// 订阅某个主题
pubSub.subscribe('topic1', console.log);
pubSub.subscribe('topic2', console.log);
// 发布某个主题
pubSub.publish('topic1','I published topic1');
pubSub.publish('topic2','I published topic2');
【观察者模式】
class Subject {
constructor() {
this.observers = [];
}
add(observer) {
this.observers.push(observer);
}
notify(...args) {
this.observers.forEach(observer => observer.update(...args));
}
}
class Observer {
update(...args) {
console.log(...args);
}
}
// 创建观察者
let ob1 =new Observer();
let ob2 =new Observer();
// 创建目标
let sub =new Subject();
// 目标sub添加观察者
sub.add(ob1);
sub.add(ob2);
// 目标sub触发事件
sub.notify('I fired event');
虽然两种模式都存在订阅者和发布者(具体观察者可认为是订阅者、具体目标可认为是发布者),但是观察者模式是由有具体目标调度的,而发布/订阅模式是统一由调度中心调度的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。