天天看點

觀察者模式 vs 釋出訂閱模式

有一回面試,面試官問:

觀察者模式,和釋出訂閱模式,有什麼差別?

我腦海中立刻閃現了《Head First設計模式》裡講的:

Publishers + Subscribers = Observer Pattern
觀察者模式 vs 釋出訂閱模式

“哼哼,我知道答案了,兄dei!”,我内心無比雞凍。

觀察者模式 vs 釋出訂閱模式

“它們是一樣的。”,我故作鎮定,嘴角露出一絲微笑,仿佛下一秒鐘面試官就會給我發offer。

面試官也笑了,“不,它們不一樣”。

然後我就:

觀察者模式 vs 釋出訂閱模式

So, 為什麼我錯了?觀察者模式(Observer pattern),和釋出訂閱模式(Publish–subscribe pattern),到底有什麼不同?

觀察者模式

所謂觀察者模式,其實就是為了實作松耦合(loosely coupled)。

用《Head First設計模式》裡的氣象站為例子,每當氣象測量資料有更新,

changed()

方法就會被調用,于是我們可以在

changed()

方法裡面,更新氣象儀器上的資料,比如溫度、氣壓等等。

但是這樣寫有個問題,就是如果以後我們想在

changed()

方法被調用時,更新更多的資訊,比如說濕度,那就要去修改

changed()

方法的代碼,這就是緊耦合的壞處。

怎麼解決呢?使用觀察者模式,面向接口程式設計,實作松耦合。

觀察者模式裡面,

changed()

方法所在的執行個體對象,就是被觀察者(Subject,或者叫Observable),它隻需維護一套觀察者(Observer)的集合,這些Observer實作相同的接口,Subject隻需要知道,通知Observer時,需要調用哪個統一方法就好了:

觀察者模式 vs 釋出訂閱模式

這裡就不貼代碼了,網上已經有大量的資料。

釋出訂閱模式

大概很多人都和我一樣,覺得釋出訂閱模式裡的Publisher,就是觀察者模式裡的Subject,而Subscriber,就是Observer。Publisher變化時,就主動去通知Subscriber。

其實并不是。

在釋出訂閱模式裡,釋出者,并不會直接通知訂閱者,換句話說,釋出者和訂閱者,彼此互不相識。

互不相識?那他們之間如何交流?

答案是,通過第三者,也就是在消息隊列裡面,我們常說的經紀人Broker。

觀察者模式 vs 釋出訂閱模式

釋出者隻需告訴Broker,我要發的消息,topic是AAA;

訂閱者隻需告訴Broker,我要訂閱topic是AAA的消息;

于是,當Broker收到釋出者發過來消息,并且topic是AAA時,就會把消息推送給訂閱了topic是AAA的訂閱者。當然也有可能是訂閱者自己過來拉取,看具體實作。

也就是說,釋出訂閱模式裡,釋出者和訂閱者,不是松耦合,而是完全解耦的。

放一張極簡的圖,給大家對比一下這兩個模式的差別:

觀察者模式 vs 釋出訂閱模式

總結

從表面上看:

  • 觀察者模式裡,隻有兩個角色 —— 觀察者 + 被觀察者
  • 而釋出訂閱模式裡,卻不僅僅隻有釋出者和訂閱者兩個角色,還有一個經常被我們忽略的 —— 經紀人Broker

往更深層次講:

  • 觀察者和被觀察者,是松耦合的關系
  • 釋出者和訂閱者,則完全不存在耦合

從使用層面上講:

  • 觀察者模式,多用于單個應用内部
  • 釋出訂閱模式,則更多的是一種跨應用的模式(cross-application pattern),比如我們常用的消息中間件

最後,我的所有文字,都是對這篇文章的拙劣模仿:Observer vs Pub-Sub pattern

對了,個人公衆号 Bridge4You,歡迎關注~

觀察者模式 vs 釋出訂閱模式

柳樹的絮叨叨

繼續閱讀