Lumen

Lumen

Eager to know more, about the world, about the intelligence, and about myself.
github

組合優於繼承

為什麼「優先考慮組合而非繼承」?#

在最近的一篇文章中,我分享了我對於項目代碼庫複雜性的沮喪。基本上,它太複雜且交織在一起。儘管我感到不適,但我必須找到解決方案,這使我接觸到了設計模式。

我聽過的其中一個原則是「優先考慮組合而非繼承」。最初,我對這兩者之間的區別只有模糊的理解,更不用說如何在我的項目中實現這一概念。然而,這段來自 ArjanCodes 的視頻 幫助我理解了其背後的原理,現在我將解釋這一點。

依賴性造成複雜性#

在設計項目時,特別是在面向對象編程中,由於不同對象之間的交互和依賴性,複雜性可能迅速上升。這種複雜性源於 依賴性

複雜的依賴性可能導致幾個問題。它可能使修改和添加新功能變得艱巨,因為你必須考慮不同對象之間的錯綜複雜的相互作用。變更可能會在整個代碼庫中產生意想不到的後果。此外,單元測試在高度依賴的代碼中變得更加困難,因為你需要測試所有情況以達到足夠的覆蓋率。

下面的圖表說明了系統依賴性的不同級別。高度依賴的系統需要測試所有可能的輸入組合。然而,通過將計算解耦為步驟,每個函數可以通過檢查單個輸入及其對應的輸出來進行驗證,這樣測試起來就容易得多。

Mermaid Loading...
不同依賴性級別的比較

複雜的繼承結構引入依賴性#

借鑒 Arjan 的例子,在純粹基於繼承的方法中,一個 Employee 類可能封裝了與員工相關的所有行為,例如 ID、年齡、性別和支付方式。對於每種類型的員工,你都會創建一個從基類派生的子類。這種方法通過繼承來解決問題。

然而,如果你將所有責任分配給一個單一的 Employee 類,隨著項目的增長及其不斷演變的需求,最終將導致一個龐大的層級樹。每個部分都依賴於其父類,這在共享相同父類的子類之間創造了間接的依賴性。修改任何基類都可能導致混亂。如果一個新變體對你現有的實現有甚至是微小的不兼容要求,你可能不得不從一個非常基礎的類繼承並重新實現所有功能。簡而言之,繼承創造了依賴性,過度使用它會使你的工作變得更加複雜,而不是簡化。

Mermaid Loading...
複雜的繼承樹

優先考慮接口#

問題不在於我們不應該創建複雜系統,而在於確保這些系統內部組件的邏輯分離。如果我們檢查前面的例子,Employee 類因為被分配了多個責任而變得問題重重。它細分了不同的員工類型並管理各種支付和佣金,這些任務可以由 單獨的實例處理

為了解決這個問題,我們可以為不同的合同類型創建一個 Contract 類,並為各種佣金創建一個 Commission 類。然後可以將這些實例傳遞給 Employee 類。只要這些保持統一的接口,我們的任務就變得簡單得多。

Mermaid Loading...
這看起來好多了,不是嗎?

結論#

設計模式對我來說相當新鮮,但我可以大致看出它們的目標 —— 降低系統的複雜性,並在可能的情況下使其模塊化。

「組合優於繼承」的理念在抽象層面上與依賴注入相似。它們都是表達同一目標的不同術語,旨在分離並保持局部的簡單性,從而增強代碼的可維護性和靈活性。

參考文獻#

為什麼組合比繼承更好 - 詳細的 Python 範例

Python 中的依賴反轉與依賴注入

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。