設計模式/原則

發佈/訂閱模式 vs 觀察者模式

GoF 原著中,告訴我們 觀察者模式 (Observer Pattern)
又稱為 發佈/訂閱模式 (Publish/Subscribe Pattern)
(以下簡稱 Pub/Sub)
 
然而,目前實務開發的背景中,
Pub/Sub 更廣泛地被指為:

用於建立一些 事件驅動 (Event-driven)訊息傳遞協議訊息導向中介軟體(MOM)
(e.g., MQTT、XMPP、SNS、JMS) 之訊息模式。

 
subscribe
 


 

模組的解耦

許多 發佈/訂閱 系統,
會在 發布者 (Publisher)訂閱者 (Subscriber) 之間,
透過 中間人 (broker) 或 Message/Event Bus… 來進行解耦。
 
使得 發佈者 與 訂閱者 彼此並不認識,
就像訂閱某個粉專,訂閱者 不需知道 發文的小編 是誰。
pub-sub
 


 

時間的解耦

訊息傳遞,可以是 同步 (synchronous)非同步/異步 (asynchronous)
(以下簡稱 sync 與 async)
在這 [註1] 也稱為 等待 (blocking) 或 非等待 (non-blocking)。

 
快遞送貨到某處,結果對方家裏沒人,若快遞癡癡地等… 他就完了,
其他貨都不用送了膩?
 
同理:

發佈訊息時,訂閱者 (Subscriber) 不一定會在線上

 
因此大部分 Pub/Sub 透過 非同步(async) 的方式,
使訊息的傳遞不需等待回應、不依賴對方為 等待接收 (blocking receive) 的狀態,
透過 先存再送 (store-and-forward) 的機制,確保訊息將可靠地送達。
 
換句話說,一旦訊息送出之後,
程式不會停止下來等待回應,而是繼續進行後續的操作,實現了時間的解偶。
 
 
[註1]: 兩者並不一定相同
 


 

再談觀察者模式

GoF 原著提到:

觀察者模式 (Observer Pattern)
可利用 『ChangeManager』封裝起複雜的更新語意,
藉此將 Subject 與 Observer 解耦,
並且,可將 ChangeManager 寫成 單例模式 (Singleton Pattern) 來使用。

 
ChangeManager
 
Singleton 其中一個好處就是 『跨平台』,
經過一些擴充,ChangeManager 即能實現分散式系統 or 跨行程/平台 的訊息傳遞。
 

你或許會認為與 Pub/Sub 頗為相似? 或根本一樣?

 


 

Pub/Sub vs. Observer Pattern

有些人說 Observer Pattern 是 一對多sync
而 Pub/Sub Pattern 是 多對多async
 
事實上,GoF 從來沒有規範
觀察者模式 (Observer Pattern) 需使用 sync,
也沒有說 Subject 不行進行擴充,
 
因此你可以看到,我撰寫的觀察者模式實作介紹中
訂閱了多個 Subject,且提醒你可以使用異步方式。
 
MQTT 的 官方文件中,則提到:

Use of the publish/subscribe message pattern
which provides one-to-many message distribution and decoupling of applications.

 
發布/訂閱 模式,提供了『一對多』的消息分佈。

Pub/Sub 並沒有『多對多』的這項規範。

 
Observer Pattern 指的『一對多』,是指單一抽象觀念的兩個層面,
並非指只能有一個具體 Subject!
 
不可否認的是,Pub/Sub Pattern 明確地,
會有一個 中間/中介 與 async (大部分) 的概念,Observer 則否。
 


 

總結

許多文件中,更常可以看到的是『mechanism』這個字眼,
發佈/訂閱 描述為一種機制或概念,
並拿來與其他訊息傳送機制做比較,如: 點對點 (point-to-point)。
 
在不同的時空背景、程式語言、使用需求,意義或許不盡相同,
有些認為 Publish/Subscribe 是 Observer 的實作面,
有些人認為他們截然不同。
 
如 XMPP 的 官方文件中
提到:

Pubsub therefore adheres to the classic Observer design pattern
and can serve as the foundation for a wide variety of applications

 
發布/訂閱 模式,遵循了經典的 觀察者設計模式
因此可作為各種應用的基礎。
 
其 RFC6121文件,也說明了:
XMPP 其存在基礎,是遵循著 Observer 或 Publish/Subscribe Pattern。
 
個人認為:

兩者是本質相同,欲具體描述使用領域或實作,才進一步做區分的『名詞』。

 
就如 泰迪軟體科技 創辦人 — Teddy Chen,
於其 Observer和Publish-Subscribe 一文中所述:

一個名詞的意義,只有在相同的 Bounded-Context 才有意義。

 
良葛格也說過:
技術名詞紛爭多

使用某個模式概念,
針對實際處理的問題實作出來的方案,
必然會有不同的調整與結果。

 
名詞是拿來溝通,不是拿來裝逼的,
理解其原理精髓,並因應需求來實作、調整和修改才最重要 😀。
 
總之
dispute
 
 

作者: 鄭中勝

喜愛音樂,但不知為何總在打程式 ?
期許能重新審視、整理自身所學,幫助有需要的人。

發表迴響