前陣子重新檢視會員註冊邏輯時,我忍不住嘆了口氣。
明明只按了一個按鈕,View Controller 裡卻直接呼叫了六、七個物件,處理驗證、網路請求、Token 儲存、通知註冊等工作。
這套流程還要在其他畫面重複使用,但我不想把整個順序和組合原封不動地複製過去。
這就是 Swift Facade Pattern 派上用場的時候。
先說結論,Facade Pattern 是把多個物件交織的複雜子系統,包裝在像 signUp() 這樣的一個方法後面。呼叫端不需要知道內部如何運作。
介面轉換、存取控制與新增功能之間的界線,可以在 Adapter・Facade・Proxy・Decorator 比較 中一目了然。
今天會用 Swift 程式碼說明如何套用這個 Pattern,也會結合我的經驗談談什麼時候適合使用,以及什麼時候反而會造成反效果。
什麼是 Facade Pattern?
Facade 原本是指建築物的「正面外觀」。
從外面看只看得到整潔的建築正面,但裡面其實充滿管線、電線和複雜設備。
軟體也是一樣。
當內部有多個類別彼此呼叫、共同運作的子系統時,就在它前面設置一個窗口。
呼叫端只要和這個窗口溝通即可。
核心就是「簡化的入口」。
Facade 不是消除複雜性,而是把複雜性關在同一處,只對外開一扇容易使用的門。
重點在於隱藏內部實作,而不是移除它。
管線依然存在,只是藏到牆後面而已。
用 Swift 實作會是這樣
只用文字不容易掌握,我們直接看程式碼。
假設會員註冊流程有三個子系統:驗證、伺服器註冊和 Token 儲存。
先看看想要隱藏的內部物件。
struct Validator { func check(_ email: String) -> Bool { email.contains("@") } }
struct AuthAPI { func register(_ email: String) -> String { "token_\(email)" } }
struct TokenStore { func save(_ token: String) { /* Keychain 儲存 */ } }
如果由 View Controller 直接呼叫這三者,程式碼會變得很凌亂。
因此由 Facade 代替呼叫端協調它們。
struct SignUpFacade {
private let validator = Validator()
private let api = AuthAPI()
private let store = TokenStore()
func signUp(email: String) -> Bool {
guard validator.check(email) else { return false }
let token = api.register(email) // 只在這裡管理內部順序
store.save(token)
return true
}
}
這樣一來,使用端只需要一行程式碼。
就像這樣:SignUpFacade().signUp(email: "[email protected]")。
呼叫端完全不必知道要先驗證,再儲存 Token。
之後即使順序改變或多了一個步驟,也只要修改 Facade 內部即可。
什麼時候適合使用,什麼時候該避免?
這裡整理了我實際使用後歸納出的判斷標準。
適合使用 Facade 的情況
- 多個物件總是按照固定順序被呼叫,而且相同程式碼在各處重複時
- 想包裝外部函式庫或複雜 SDK,並換成適合自己 App 的簡單名稱時
- View Controller 知道太多事情,想替它減輕負擔時
反而適合避免的情況
- 子系統原本就很簡單,沒有太多需要隱藏的內容時(只是平白多一層)
- 每次都需要細緻控制,最後仍得繞過 Facade 直接呼叫內部物件時
這裡有一點我想特別指出。
Facade 並不是要「阻擋」對內部的存取。
它只是提供一條簡單的路;有需要時,仍然可以直接使用內部物件。
因此,它和想要控制所有存取方式的其他 Pattern,性質並不相同。
幾個常見問題
Q. Facade 和一般的 Utility Function 有什麼不同?
Utility Function 通常只包含一項獨立功能,而 Facade 的目的,是協調多個物件之間的合作與順序。
差別在於「隱藏的是什麼」。
Q. 一定要做成 Protocol 嗎?
不一定需要。
不過,如果想在測試中用假物件替換 Facade,先用 Protocol 抽象化會方便許多。
Q. 我常把它和 Adapter Pattern 搞混。
Adapter 的目的,是讓不相容的介面彼此配合;Facade 的目的,則是用簡單的方式呈現複雜內容。
記住兩者的目的不同,就容易理解了。
總結
每次看到一大串複雜呼叫時,不妨問問自己:「能不能把它包成一個方法?」
光是這個問題,就常常能讓程式碼變得好讀許多。
Facade 不是華麗的 Pattern,卻是實務上最常派上用場的可靠工具之一。
建議你就從今天的會員註冊範例開始,輕鬆試著實作看看。

