观察者模式
观察者模式有一个别名叫“发布-订阅模式”,或者说是“订阅-发布模式”,观察者(Observer)和被观察者(Subject)是联系在一起的,当观察目标发生改变时,逐个通知观察者。我们可以用报纸期刊的订阅来形象的说明,当你订阅了一份报纸,每天都会有一份最新的报纸送到你手上,有多少人订阅报纸,报社就会发多少份报纸,报社和订报纸的客户就是“一对多”的依赖关系。
简单的代码实现:
// 报刊
class Subject {
constructor() {
// 存放订阅者
this.observers = [];
}
// 添加订阅者
add(observer) {
this.observers.push(observer);
}
// 新报纸
updata(newMessage) {
this.notify(newMessage);
}
// 通知订阅者
notify(Message) {
this.observers.forEach((observer) => {
observer(Message);
})
}
}
// 定义订阅者A
const observerA = (newspaper) => {
console.log(newspaper + "——observerA");
};
// 定义订阅者B
const observerB = (newspaper) => {
console.log(msg + "——observerA");
};
var subject = new Subject();
subject.add(observerA);
subject.add(observerB);
subject.updata("这是今天的报纸");
//打印结果:
// 这是今天的报纸——observerA
// 这是今天的报纸——observerB
发布订阅模式
因为 Subject 就像一个发布者(Publisher),Subject 通知观察者(Observer)就像一个发布者通知他的订阅者(Subscriber)。经过时间的沉淀,发布订阅模式已经独立于观察者模式,成为另外一种不同的设计模式。
在现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为调度中心或事件通道,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。
举一个例子,你在微博上关注了 A,同时其他很多人也关注了 A,那么当 A 发布动态的时候,微博就会为你们推送这条动态。A 就是发布者,你是订阅者,微博就是调度中心,你和A是没有直接的消息往来的,全是通过微博来协调的(你的关注,A 的发布动态)。
简单的代码实现:
// 微博
class Broker {
constructor() {
// 存放关注者
this.subscribers = [];
}
// 添加关注者
on(subscriber) {
this.subscribers.push(subscriber);
}
// 通知关注者
notify(msg) {
this.subscribers.forEach((subscriber) => {
subscriber(msg);
});
}
}
// 被关注者A
class Publisher {
constructor(broker) {
this.broker = broker;
}
// 发布动态
emit(message) {
this.broker.notify(message);
}
}
// 定义关注者 A
const subscriberA = (msg) => {
console.log("关注者 A 收到一条动态:" + msg);
};
// 定义关注者 B
const subscriberB = (msg) => {
console.log("关注者 B 收到一条动态:" + msg);
};
const broker = new Broker();
broker.on(subscriberA);
broker.on(subscriberB);
// 被关注者入驻微博
const publisher = new Publisher(broker);
publisher.emit("今天天气真好");
//打印结果:
// 关注者 A 收到一条动态:今天天气真好
// 关注者 B 收到一条动态:今天天气真好
区别
用下图表示这两个模式最重要的区别:
区别总结:
- 在观察者模式中,观察者是知道 Subject 的,Subject 一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。
- 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
- 观察者模式大多数时候是同步的,比如当事件触发,Subject 就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。
- 观察者 模式需要在单个应用程序地址空间中实现,而发布-订阅更多的是跨应用程序模式。
优缺点
观察者模式
**
- 优点:响应式,目标变化就会通知观察者,这是观察者最大的有点
- 缺点:不灵活,相比订阅发布模式,由于目标和观察者是耦合在一起的,所以观察者模式需要同时引入目标和观察者才能达到响应式的效果。而订阅发布模式只需要引入事件中心,订阅者和发布者可以不在一处
订阅发布模式
**
- 优点:
- 灵活由于订阅发布模式的发布者和订阅者是解耦的,只要引入订阅发布模式的事件中心,无论在何处都可以发布订阅。同时订阅发布者相互之间不影响
- 订阅发布模式在使用不当的情况下,容易造成数据流混乱,所以才有了 React 提出的单项数据流思想,就是为了解决数据流混乱的问题
- 缺点:
- 容易导致代码不好维护灵活是有点,同时也是缺点,使用不当就会造成数据流混乱,导致代码不好维护
- 性能消耗更大订阅发布模式需要维护事件列队,订阅的事件越多,内存消耗越大
- 容易导致代码不好维护灵活是有点,同时也是缺点,使用不当就会造成数据流混乱,导致代码不好维护