很多 GoF 模式是在補「物件導向語言缺少一級函數」的洞。換到函數式語言,同樣的意圖往往直接用高階函數、不可變資料、pattern matching 就達成了——模式沒消失,只是換了形態。
🧠 When to Use
TIP
這頁不是「哪個範式比較好」,而是幫你判斷:手上的問題,用「物件 + 多型」表達比較自然,還是用「函數 + 資料變換」比較自然。
- 看到一個 GoF 模式時,先問:它在補語言的哪個缺口? 在你的語言裡那個缺口還在嗎?
- 決定一段邏輯要做成有狀態的物件還是純函數管線。
- 在混合範式語言(Kotlin、Scala、現代 C#)裡,挑兩者中較輕的表達。
⚖️ Structure & Variants
同一意圖、兩種形態對照
| 意圖 | OOP 形態 | FP 形態 |
|---|---|---|
| 可替換演算法 | Strategy(介面 + 實作類) | 傳一個函數 |
| 疊加行為 | Decorator(同介面包裝) | 高階函數 g(f) / middleware |
| 依型別分派 | Visitor / 多型 | pattern matching / 代數資料型別 |
| 延遲建立 | Factory + 物件 | thunk / 惰性求值 |
| 通知 | Observer(註冊監聽者) | stream / reactive / event as data |
- 重點不是「FP 不用模式」,而是一級函數讓很多模式縮成一行。
什麼時候 OOP 形態仍然較好
- 行為伴隨狀態與不變式、需要封裝(帳戶餘額、連線池)→ 物件較自然。
- 需要一族相關操作的多型分派且型別開放擴充 → 介面 + 實作勝過巨大 match。
- 團隊 / 既有程式庫是 OO 慣例時,硬塞 FP 風格反而增加認知成本。
什麼時候 FP 形態較好
- 資料進來→變換→出去的管線(解析、轉檔、聚合)→ 純函數 + 不可變資料。
- 邏輯無共享狀態、想好測試與並行 → 純函數沒有隱藏依賴。
- 「行為當資料傳遞」是核心(callback、策略、事件)→ 一級函數直接表達。
⚠️ Misuse & Anti-patterns
- 教條主義:堅持「萬物皆物件」或「萬物皆純函數」,把不合適的問題硬塞進單一範式。
- 把 GoF 當聖經背:在有一級函數的語言裡,仍機械地開
interface XxxStrategy+ 一堆實作類,只為了一個 lambda 能解的事。 - 混用無章法:同一模組一半 OO 一半 FP 又沒邊界,讀者得不斷切換心智模型。範式可混,但要劃清邊界。
🔑 Takeaways
- 多數 GoF 模式在補「OO 缺一級函數」的洞;換範式時,先問模式補的缺口還在不在。
- 有狀態 / 要封裝不變式 / 開放型別多型 → 偏 OOP;資料變換管線 / 無共享狀態 → 偏 FP。
- 範式是工具不是信仰:可混用,但要劃清邊界、選較輕的表達。
No notes yet — jot your takeaways or Q&A here.