物件越多,程式碼越可能在某個時刻變成義大利麵。當同一個畫面的 View Controller、網路、快取和記錄器開始彼此直接呼叫時,修好一處往往又弄壞另一處。
這時通常會想到 Mediator、Observer、Facade 這三種模式。三者都被介紹為「整理物件通訊」的方法,但實際上要解決的問題各不相同。
Mediator 將互相糾結的關係集中控制,Observer 以一對多通知處理狀態變更,Facade 則用單一入口整理複雜內部。
只要記住這一句,就完成一半了。接下來會搭配程式碼說明各自的使用時機與差異。
先用一句話總結三種模式
先整理核心概念,方便混淆時回頭查看。
- Mediator — 多個物件不直接互相參照,而是透過一個中介者溝通
- Observer — 一個物件的狀態變更時,自動通知多個訂閱它的物件
- 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
核取方塊和按鈕不必直接知道彼此,中介者會代為執行「同意後啟用提交」的規則。
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。
面試時可以這樣回答
Q. Mediator 和 Observer 有什麼不同?
Observer 是一對多結構,Subject 的狀態變更會沿單一方向傳播給訂閱者。Mediator 則是多對多結構,由中介者在中央協調錯綜物件之間的互動規則。方向性與關係複雜度是兩者的核心差異。
Q. Facade 也能降低耦合度,和 Mediator 有什麼不同?
Facade 在子系統前提供簡易介面,降低呼叫端與系統之間的使用複雜度。Mediator 則是協調同儕物件之間的相互通訊。可以回答:「Facade 是單向簡化,Mediator 是互動協調。」
與其背誦三種模式,不如先問自己目前的程式碼是「關係糾結的問題」、「變更傳播的問題」,還是「流程複雜的問題」。答案確定後,模式自然會跟著出現。今天的重構就挑一種套用看看。

