軟體設計

Mediator vs Observer vs Facade 完整比較:3 種物件通訊模式

Mediator 在中央協調錯綜複雜的物件關係,Observer 以一對多通知狀態變更,而 Facade 則用單一入口包裝複雜內部。本文透過 Swift 範例比較三種模式的差異與選擇依據。

閱讀 4 分鐘
Mediator vs Observer vs Facade 完整比較:3 種物件通訊模式 封面圖

物件越多,程式碼越可能在某個時刻變成義大利麵。當同一個畫面的 View Controller、網路、快取和記錄器開始彼此直接呼叫時,修好一處往往又弄壞另一處。

這時通常會想到 Mediator、Observer、Facade 這三種模式。三者都被介紹為「整理物件通訊」的方法,但實際上要解決的問題各不相同。

Mediator 將互相糾結的關係集中控制,Observer 以一對多通知處理狀態變更,Facade 則用單一入口整理複雜內部。

只要記住這一句,就完成一半了。接下來會搭配程式碼說明各自的使用時機與差異。


先用一句話總結三種模式

先整理核心概念,方便混淆時回頭查看。

  1. Mediator — 多個物件不直接互相參照,而是透過一個中介者溝通
  2. Observer — 一個物件的狀態變更時,自動通知多個訂閱它的物件
  3. Facade — 在複雜子系統前建立單一簡易介面,將其隱藏

即使同樣是「整理通訊」,著重點仍然不同。

Mediator 降低關係的複雜度,Observer 處理變更的傳播,Facade 則降低使用的複雜度


Mediator vs Observer,有什麼不同?

這兩者最容易混淆,因為它們都讓物件不必直接呼叫彼此。

差異在於關係的方向

Observer 的方向很明確。一個 Subject 發生變更後,會沿單一方向傳遞給訂閱者。像聊天室收到新訊息時,畫面、通知徽章和聲音各自做出反應。

Mediator 的方向則彼此交織。按下按鈕會啟用文字欄位,文字欄位又會改變儲存按鈕的狀態,依此類推。這種多對多關係由中介者代為協調。

// Observer:狀態變更沿單一方向傳播
protocol Observer: AnyObject { func update(_ count: Int) }

final class Cart {
    private var observers: [Observer] = []
    var items = 0 { didSet { observers.forEach { $0.update(items) } } }
    func subscribe(_ o: Observer) { observers.append(o) }
}

final class Badge: Observer {
    func update(_ count: Int) { print("購物車徽章: \(count)") }
}

let cart = Cart()
cart.subscribe(Badge())
cart.items = 3
// 輸出:購物車徽章: 3

購物車一變更,徽章就會自動跟著更新。Cart 不需要知道 Badge 是什麼。

相對地,Mediator 將物件之間的規則交由中介者管理。

// Mediator:由中介者管理糾結的規則
final class FormMediator {
    var isAgreed = false
    func agreedChanged(_ value: Bool, submit: Button) {
        isAgreed = value
        submit.isEnabled = value   // 規則:同意後啟用提交
    }
}

final class Button { var isEnabled = false }

let submit = Button()
let mediator = FormMediator()
mediator.agreedChanged(true, submit: submit)
print(submit.isEnabled)
// 輸出: true

核取方塊和按鈕不必直接知道彼此,中介者會代為執行「同意後啟用提交」的規則。

對比 Mediator 雙向協調與 Observer 單向通知的示意圖
左側是錯綜關係的協調,右側是單向通知,兩者性質不同

Facade 的性質稍有不同

Facade 的目的和前兩者本身就不同。它不是協調通訊,而是將複雜內部包裝起來使其不可見的模式。

假設完成一筆訂單必須依序呼叫付款、庫存、配送和通知模組。呼叫端的程式碼很快就會變得凌亂。

Facade 會將這些整合成一個入口。

final class OrderFacade {
    func placeOrder(_ id: String) {
        Payment().charge(id)
        Stock().reduce(id)
        Delivery().book(id)
        print("完成訂單: \(id)")
    }
}

OrderFacade().placeOrder("A-1024")
// 輸出:訂單完成: A-1024

從外部只要呼叫一次placeOrder即可。內部有幾個模組都不必知道。

重點就在這裡。Facade 不是讓物件彼此溝通,而是簡化呼叫端與複雜系統之間的關係。方向朝向內部。


一眼比較

以下整理我在 2026 年實務上的分類方式。

分類 Mediator Observer Facade
解決的問題 錯綜複雜的多對多關係 狀態變更傳播 隱藏複雜內部
關係方向 彼此交織(中央協調) 一對多(單向) 呼叫端→系統
耦合度變化 降低物件間耦合 分離主體與訂閱者 降低使用複雜度
代表範例 表單驗證、聊天室協調 通知、資料繫結 付款與訂單整合 API

放進表格後,就能明顯看出三者並不重疊。


何時使用,何時避免

模式濫用反而會造成傷害。把所有錯綜關係都塞進 Mediator,很容易讓中介者變成 God object。

  • Mediator — 當 3~4 個以上的物件彼此直接參照,且規則互相糾結時使用。但規則簡單時請避免,否則中介者會過度膨脹。
  • Observer — 當多個地方都需要知道某一處的變更時使用。忘記取消訂閱可能造成記憶體洩漏,請特別注意。
  • Facade — 想隱藏複雜的呼叫流程時使用。在必須細緻控制內部的地方,反而會造成阻礙。

一句話總結:關係糾結用 Mediator、需要通知變更用 Observer、想隱藏流程用 Facade

桌上有一台開啟 Swift 程式碼的螢幕,並貼著 FACADE 便利貼
歸根究柢,程式碼能變得多乾淨,就是選擇模式的判準

面試時可以這樣回答

Q. Mediator 和 Observer 有什麼不同?

Observer 是一對多結構,Subject 的狀態變更會沿單一方向傳播給訂閱者。Mediator 則是多對多結構,由中介者在中央協調錯綜物件之間的互動規則。方向性與關係複雜度是兩者的核心差異。

Q. Facade 也能降低耦合度,和 Mediator 有什麼不同?

Facade 在子系統前提供簡易介面,降低呼叫端與系統之間的使用複雜度。Mediator 則是協調同儕物件之間的相互通訊。可以回答:「Facade 是單向簡化,Mediator 是互動協調。」


與其背誦三種模式,不如先問自己目前的程式碼是「關係糾結的問題」、「變更傳播的問題」,還是「流程複雜的問題」。答案確定後,模式自然會跟著出現。今天的重構就挑一種套用看看。

延伸閱讀