观察者模式
观察者模式有一个别名叫“发布-订阅模式”,或者说是“订阅-发布模式”,观察者(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);})}}// 定义订阅者Aconst observerA = (newspaper) => {console.log(newspaper + "——observerA");};// 定义订阅者Bconst 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);});}}// 被关注者Aclass Publisher {constructor(broker) {this.broker = broker;}// 发布动态emit(message) {this.broker.notify(message);}}// 定义关注者 Aconst subscriberA = (msg) => {console.log("关注者 A 收到一条动态:" + msg);};// 定义关注者 Bconst 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 提出的单项数据流思想,就是为了解决数据流混乱的问题
- 缺点:
- 容易导致代码不好维护灵活是有点,同时也是缺点,使用不当就会造成数据流混乱,导致代码不好维护
- 性能消耗更大订阅发布模式需要维护事件列队,订阅的事件越多,内存消耗越大
- 容易导致代码不好维护灵活是有点,同时也是缺点,使用不当就会造成数据流混乱,导致代码不好维护
