軟體開發面臨複雜多變且不可預測的需求。六大設計原則並非教條,而是應對複雜性的利器。實務上不需每條都遵循至極致,但應根據專案實際需求盡量遵守。能真正融會貫通並落地的,往往是經驗豐富的資深工程師。
定義:一個類別應該只有一個引起它變更的原因。即一個介面/類別只做一件事。
實戰範例:錯誤的 User 類別混雜屬性操作與業務行為。正確做法拆分為 UserBO (業務物件,存屬性) 與 UserBL (業務邏輯,存行為)。
方法層面:避免「萬用方法」(如 changeUserInfo(user, params string[] options)),應拆分為 ChangePassword、ChangeAddress 等單一職責方法。
結論:介面必須單一職責;類別設計盡量只有一個變更原因,但不可過度拆分導致維護困難。
核心定義:凡是父類別出現的地方,子類別一定可以出現,且替換後不會出錯。反向不一定成立。
四大規範:
ToyGun 繼承 Gun 但 Shoot() 為空實作,違反 LSP。解決方案:斷開繼承,改用組合/關聯。HashMap,子類別可放大為 Map(逆變)。若縮小則會導致邏輯混亂(重載而非覆寫)。核心:面向介面程式設計。三大表現:
經典範例:Driver 直接依賴 Benz → 改為依賴 ICar 介面,新增 BMW 只需修改客戶端注入物件,Driver 完全不動。
三種依賴注入方式:建構子注入、Setter 注入、介面注入(方法參數注入)。
核心差異:SRP 關注「職責」(業務邏輯劃分),ISP 關注「介面大小」(介面方法盡量少)。
四大規範:
SimpleSearch 給學生,AdminSearch 給管理員)。核心:一個物件應盡量少了解其他物件。只知道你有哪些 public 方法可呼叫,其他細節與我無關。
改進範例:老師點名案例。
違反:老師直接 new 學生清單、new 體育委員、呼叫體育委員的 Count(List<Student>) → 老師耦合 Student、StudentLeader。
改進:老師只依賴 StudentLeader,呼叫無參數 Count(),學生清單由體育委員內部管理 → 老師與 Student 解耦。
權衡:過度解耦會產生大量中介類別,增加理解與維護成本。需根據實際權衡利弊。
核心:軟體實體應對擴充開放,對修改關閉。透過擴充實現變化,而非修改既有代碼。
實戰:圖書銷售系統打折需求
GetOffPrice)GetPrice 邏輯OffNovelBook : NovelBook,覆寫 GetPrice() 實現打折邏輯客戶端僅需替換實例化類別(new OffNovelBook(...)),既有代碼零修改,完美符合 OCP。
六大原則相輔相成,SRP 奠基、LSP 守護繼承、DIP 解耦合、ISP 精簡介面、LoD 控制耦合深度、OCP 指引擴充策略。實務中靈活運用、權衡取捨,才是架構師的核心功力。