本文將通過示例討論 Java 開發如何實踐 SOLID 原則。
2000年,Robert C.Martin 在《設計原則和設計模式》論文中首次提出 SOLID 概念。Michael Feathers 對這些內容進行提煉並提出 SOLID 縮寫。
SOLID 是什麼?如何幫助我們編寫更好的代碼?簡單地說,Martin 和 Feathers 提出的設計原則提倡構建可維護性更高、更容易理解和更靈活的軟件。隨著程序規模日益增長,設計原則有助於降低系統複雜性並減少後續開發中可能遇到的麻煩。SOLID 原則包含下面五個概念:
- 單一職責原則(SRP)
- 開閉原則(OCP)
- 裡式替換原則(LSP)
- 接口隔離原則(ISP)
- 依賴倒置原則(DIP)
讓我們通過一個示例來理解 SOILD 原則。SOLID 原則中每一條都單獨撰寫了文章,通過 「好的」和「壞的」設計對原則進行解釋。
在實際開發中,設計 class 應牢記這五條 SOLID 原則。不僅如此,它們還是設計應用時需要遵循的最佳實踐。
1.單一職責(SRP)
“一個類應該有且只賦予一個職責”
每個類都應該賦予單一職責,而且這個職責應該完全封裝在類中。引起類變化的因素永遠不要超出一個。單一職責表示 SOLID 五項原則中的 “S”,在面向對象編程實踐中意味著編寫設計良好、可讀性強、易於維護、易於升級和修改的代碼。
實踐總結
- 如果無法給 class 指定一個有意義類名,那麼可能該類被賦予的職責過多。
- 每個 Web 應用中的對象都應賦予一個職責,所有對象 service 都應專注於該職責(SRP)。
- 如果某個 Java 類提供了多個功能,那麼兩個功能之間可能會產生耦合。即使只更改一個功能,也可能破壞耦合的關聯功能。因此需要額外測試,以免對生產環境造成損害。
2. 開閉原則(OCP)
這是應用程序設計應當牢記的第二個重要原則。開閉原則指出:
“軟件應該對擴展開放,但對修改關閉”。
簡單地說,類、模塊和函數等軟件實體應該對擴展開放,對修改關閉。開閉原則表示 SOLID 五項原則中的“O”,在面向對象編程實踐中意味著編寫設計良好、可讀性強、易於維護、易於升級和修改的代碼。
實踐總結
- 對擴展開放:class 設計在應對新需求時可以方便地加入新功能。
- 對修改關閉:除了修改 bug,否則不要改動已經設計好的類。
- 加入新功能時,設計和編碼應該儘可能避免修改已有代碼,最好不修改。
- 擴展已有功能時,應避免緊耦合:不要使用 if-else 或者 switch-case,請根據需要重構代碼。
- 實現技術:繼承、多態、泛型。
- 適用模式:策略模式、模板方法。
3. 里氏替換原則(LSP)
裡式替換原則:
“派生類型必須可以完全替換其基類型。”
裡式替換原則表示 SOLID 五項原則中的 “L”,在面向對象編程實踐中意味著編寫設計良好、可讀性強、易於維護、易於升級和修改的代碼。
實踐總結
- 該原則適用於繼承層次結構,是開閉原則的一種擴展。
- 這意味著派生出的新類必須保證不會改變基類的行為。基本上,派生類提供的功能只會比基類多。
- 如果派生類行為超出了基類客戶端的預期,則違反了里氏替換原則。比如派生類拋出一個基類不會拋出的異常,或者派生類的功能有副作用。必須考慮客戶端程序如何使用類繼承結構。有時需要重構代碼以糾正不符合里氏替換原則的部分。
4. 接口隔離原則(ISP)
該原則適用於接口,之前的單一職責原則適用於類。接口隔離原則:
“不應強迫客戶實現對自身無用的方法”。
SOLID 五項原則中的“I”表示接口隔離原則,它意味著應將較大的接口拆分為較小的接口。這樣可以確保接口的實現類只需要關心它們感興趣的方法。
5. 依賴倒置原則(DIP)
依賴倒置原則:
高層模塊不應依賴於底層模塊。兩者都應依賴其抽象。
抽象不應當依賴細節。細節應當依賴於抽象。
依賴倒置原則表示 SOLID 五項原則中的 “D”,在面向對象編程實踐中意味著編寫設計良好、可讀性強、易於維護、易於升級和修改的代碼。
實踐總結
- 契約式設計。
- 設計中每個依賴項都應該是接口或抽象類。不應當依賴任何具體類。
- 工廠類與抽象工廠可以用作依賴框架,也有像 Spring IOC(控制反轉容器)這樣的專門框架。
閱讀更多 Java高級架構師 的文章