# 观察者模式

所谓观察者模式,其实就是为了实现 松耦合(loosely coupled)

用《Head First设计模式》里的气象站为例子,每当气象测量数据有更新,changed() 方法就会被调用,于是我们可以在 changed() 方法里面,更新气象仪器上的数据,比如温度、气压等。

但是这样写有个问题,就是如果我们想在 changed() 方法被调用时,更新更多的信息,比如湿度,那就需要去修改 changed() 的代码,这就是紧耦合的坏处。

怎么解决呢?使用观察者模式,面向接口编程,实现松耦合

观察者模式里面,changed() 方法所在的实例对象,也就是被观察者(Subject,或者叫 Observable),它只需要维护一套观察者(Observer)的集合,这些 Observer 实现相同的接口,Subject 只需要知道,通知 Observer 时,需要调用那个统一方法就好了:

img

# 发布订阅模式

很多人都和我一样,认为发布订阅模式里面的 Publisher,就是观察者模式里面的 Subject,而 Subscriber 就是 Observer。Publisher 变化时,就会去主动通知 Subscriber。

其实并不是。

在发布订阅模式里,发布者并不会主动通知订阅者,换句话说,发布者和订阅者彼此互不相识。

互不相识?那么他们是如何通信的?

答案是,通过第三者,也就是在消息队列里面,我们常说的经纪人 Broker

img

发布者只需要告诉 Broker,我要发送的消息,topic 时 AAA;

订阅这只需要告诉 Broker,我要订阅的消息是 AAA;

于是当 Broker 收到发布者发过来的消息时,就会把消息推送给订阅方,当然也有可能是订阅方主动过来取,具体看实现方式。

也就是说,发布订阅模式里,发布者和订阅者这件不是松耦合,而是完全解耦。

放一张极简图给大家对比:

img

# 总结

从表面上看:

  • 观察者模式里,只有两个角色 —— 观察者 + 被观察者
  • 而发布订阅模式里,却不仅仅只有发布者和订阅者两个角色,还有一个经常被我们忽略的 —— 经纪人Broker

往更深层次讲:

  • 观察者和被观察者,是松耦合的关系
  • 发布者和订阅者,则完全不存在耦合

从使用层面上讲:

  • 观察者模式,多用于单个应用内部
  • 发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件