什麼是物件導向(OO)?教科書常說它是「真實世界的模擬」,或用三特質定義:封裝、繼承、多型。
但從架構師來看,前兩特質非 OO 獨有,唯有第三個特質——多型,才是 OO 賦予架構師的超能力。
一、重新檢視 OO 的三大特質#
1. 封裝 (Encapsulation)#
- 定義: 隱藏資料與實作細節,僅暴露介面
- 事實: OO 沒有發明封裝。
早期的 C 透過 header files (.h) 和實作檔 (.c) 就能達成完美的封裝。
反而是許多 OO 語言(如 Java, C++)破壞了部分封裝性
(因得把private成員宣告在header裡) - 結論: 封裝不是 OO 的獨門絕技
2. 繼承 (Inheritance)#
- 定義: 在封閉範圍內重新宣告一組變數和函式
- 事實: C 也可透過
struct的記憶體佈局模擬繼承。
但 OO 確實讓繼承變更容易、方便 - 結論: OO 優化了繼承,但這不是變革性創新
3. 多型 (Polymorphism)#
- 定義: 透過統一的介面操作不同物件
- 本質: 函式指標(Function Pointers) 的應用
- 貢獻: OO 出現前,用函式指標非常危險(需手動維護,易產生難追查的 Bug)。
OO 將多型變安全且方便,成為隨手可得的工具 - 結論: OO 的真正威力所在
二、多型的架構力量:依賴反轉#
為什麼多型如此重要?因它允許我們打破傳統「控制流程」與「原始碼依賴」間的鎖鏈。
1. 傳統結構 (無多型)#
- 控制流程: 高層呼叫低層模組(Main ➡️ High Level ➡️ Low Level)
- 依賴關係: 原始碼依賴方向緊貼著控制流程。呼叫者必須
import或include被呼叫者 - 後果: 高層策略被迫依賴低層細節,導致高層策略無法獨立於細節變更
flowchart LR
subgraph 傳統結構
M1[Main] -->|呼叫| HL1[High Level]
HL1 -->|呼叫| LL1[Low Level]
M1 -.->|依賴| HL1
HL1 -.->|依賴| LL1
end2. 多型結構 (依賴反轉)#
透過多型(介面),我們可以反轉依賴方向:
- 控制流程: 仍是 High Level ➡️ Low Level
- 依賴關係: Low 實作 High Level 定義的介面,因此 Low 依賴 High Level
- 結果: 高層策略不再依賴低層細節,而是低層細節依賴高層策略
flowchart LR
subgraph 多型結構
HL2[High Level] -->|呼叫| I[Interface]
LL2[Low Level] -.->|實作/依賴| I
end
style I fill:#fff3cd,stroke:#856404
style HL2 fill:#d4edda,stroke:#155724
style LL2 fill:#cce5ff,stroke:#004085OO 的真正威力在於多型。 它讓架構師能控制依賴方向,實現「插件架構」——讓低層細節成為高層策略的外掛。
