🕐 ~8 分鐘閱讀
📝 關於這篇文章的筆記
這篇文章是基於我個人學習筆記關於物件導向程式設計(OOP)和SOLID原則。為了讓筆記更易閱讀且實用——對我及他人而言——我使用了AI輔助開發和整理成博客文章。想法、學習過程和理解屬於我;AI幫助在寫作和呈現方面。
易讀且易修改的程式碼並非偶然。每個令人愉悅的程式碼庫背後,都有一系列引導其組織與連接方式的觀念。
本文探討這段完整的旅程——從什麼是物件導向程式設計(OOP),物件如何相互關聯,壞設計的樣貌,直至最終:統合所有內容的五項SOLID原則。
我們開始吧。
第一部分:什麼是物件導向程式設計?
物件導向程式設計 (OOP) 是一種反映現實世界的程式碼寫法。它不是一長串的指令,而是將相關的資料和行為分組到 物件 中。
🤖 想像一下玩具機器人。機器人有 屬性 (顏色, 高度, 電池) 和 行為 (行走, 語言, 挥手)。在物件導向程式設計中,那個機器人是物件 — 而用來製造它的藍圖稱為 class.
兩個關鍵詞語:
- Class — 藍圖 (範本)
- Object — 由該藍圖創建的實體
四大OOP支柱
| 支柱 | 功能 |
|---|---|
| 繼承 | 子類別繼承自類別的屬性和行為 |
| 封裝 | 隱藏內部數據 — 外部只能透過指定路徑存取 |
| 抽象化 | 內部細節被隱藏;僅顯示需要使用的部分 |
| 多形性 | 相同的動作可以根據對象的不同而表現出不同的行為 |
第二部分:對象如何相互關聯
對象並非獨立存在。它們相互連接、協作並依賴——並類型 的重要性
協會
兩個物件互相認識並可以互動。有三種關鍵關係:
- 一對一 — 一個人一個護照
- 一對多 — 一個老師,很多學生
- 多對多 — 很多學生,很多課程
在關聯中,當一個對象「擁有」另一個對象時,它們之間的關係可以是:
- 聚合 (松散) — 子對象可以在其父對象不存在時獨立存在。書包裡有書,但即使書包被丟棄,書仍然存在。
- 組合 (緊密) — 子對象無法在其父對象不存在時獨立存在。房子有房間;如果房子被摧毀,房間也隨之消失。
依賴
暫時的使用關係。一個類別在方法內使用另一個類別,但不永遠保存它。比關聯性弱.
擴充& 執行
- 擴充 — 從多個類別中提煉共同特性到一個超類別(繼承)
- 執行 — 一個實現介面的類,承諾履行已定義的合約
第三部分:設計不良是什麼樣子?
在學習其規範之前,重要的是要理解我們正在避免什麼。Robert C. Martin確定了三種設計不良的症狀:
🪨 僵固性 — 系統難以更改。觸及一點,許多其他部分也需更新。開發者因而擔憂進行變更。
🍪 脆弱性 (Kerapuhan) — 當你進行變更時,系統會在預期之外的場所損壞。你修復了支付模組的錯誤,突然間電子郵件通知停止運作。
🏗️ 固定性 (Ketidakmampuan Dipindahkan) — 有用的組件無法重用。它們與環境過於磨損,因此移除它們需要比從頭開始重寫更長的時間。
三者都有相同的根本原因:組件之間依賴管理不良。
第四部分:SOLID
SOLID 是五項直接解決上述問題的原則。每項都針對特定的設計失敗.
S — 單一責任原則
"一個模組必須對於一個,且僅僅是一個,參與者負責。"
每一個類別必須有一個,且僅僅是一個,改變的理由. — ia 服務一個角色 (一個利益相關者群組).
👨🍳 一名餐廳僱員同時擔任廚師、收銀員、保安和送餐員是等待發生的災難。一個角色的變更會干擾所有其他角色.
分開你的 class。每個 class 一個責任.
O — 開放封閉原則
"軟體工具必須開放以供新增,但必須封閉以供修改。"
透過擴展的方式新增新行為 — 而不是編輯已運行的舊代碼.
🔌 插頭讓你無需拆解線纜即可連接新設備。這就是實際中的 OCP。
當需求改變時,在舊的代碼旁邊添加新的代碼 — 不要重寫已經運行的代碼.
L — Liskov替換原則
"如果S是T的子類型,那麼類型為T的對象可以用類型為S的對象來替換,而不改變程序的正確性。"
一個子類別必須完全可以替換 父類別。每一個父類別所建立的承諾,都必須由子類別來履行.
🤖 如果父類別機器人會煮食物,子類別機器人也必須會煮食物 — 不能丟出錯誤訊息或保持沉默而不做任何事.
如果你的子類別有空的 method,提供 stub 實現,或拋出 "不支援" 錯誤 — 這是 Liskov 替換原則的違反.
我 — 接口隔離原則
"客戶不應被強迫依賴他們不使用的介面。"
不要製作過大的介面,強迫類別實現他們不需要的方法。將介面拆分成更專注的小部分。
🍴當客戶僅訂購湯時,不要給他們每個餐廳的牛排刀、湯勺、叉子和fondue夾。
較小的介面 = 更狹窄的依賴 = 位置更明確的變更.
D — 依賴反轉原則
"高階模組不應依賴低階模組。兩者都應依賴抽象化。"
商業邏輯不應直接關聯到具體實現。它應該通過介面來溝通。 — 低階細節實現該介面.
🤖 請勿將烙鐵夾焊接到機器人手上。給它安裝標準連接器,讓工具可以更換自如.
這就是為什麼基礎設施(資料庫、API、檔案系統)可以更換而不觸及商業邏輯.
簡要總結:SOLID 簡介
| 原則 | 所解決的問題 | 關鍵問題 |
|---|---|---|
| 單一職責原則 | 類別負擔過多任務 | 「此類別是否服務超過一個利害關係人群組?」 |
| 開放封閉原則 | 修改舊代碼以增加功能 | 「這是否可以作為擴展而不是修改?」 |
| 後置子類別原則 | 損壞的繼承階層 | "子女能否取代父母而不受損害?" |
| ISP | 過胖的介面與未使用的method | "這個class是否被迫實現不需要的功能?" |
| DIP | 商業邏輯與基礎設施綁定 | "高階程式碼是否依賴於本應不依賴的具體類別?" |
從哪裡開始?
如果你是第一次實施這個:
- 從單一職責原則開始 — 找到"負責太多"的類別並拆分
- 檢查繼承以查找違反里氏替換原則 — 空方法是一個警告標誌
- 在基礎設施邊界添加介面 — 這就是實踐中的DIP
這些原則不是清單。它們是你每次坐下来寫代碼時都需要提出的問題
最初發表於sanudin.dev











