Skip to main content

依賴反轉原則

定義

High level modules should not depend upon low level modules.
Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.

說明

  1. 高層次的模組不應該依賴於低層次的模組,兩者都應該依賴於抽象介面。
  2. 抽象介面不應該依賴於具體實現。而具體實現則應該依賴於抽象介面。

實作建議

  1. 每個類別都需要有介面或抽象類別
  2. 使用的變數型別應該盡量是抽象而不是具體類別。
  3. 盡量不要從具體類別繼承。

    當然實務上沒有對的情境,但如果已經知道繼承會導致一些衍伸的問題,那在做這個決定之前,更應該好好思考一下,是否能夠用繼承介面來解決,又或者是有其他的做法可以處理。

  4. 結合里氏替換原則的內容,可以得出一個大致的規範。

    介面:負責定義 public 的方法和屬性 抽象類:負責定義建構函式部分的實現

實例

需求

// ...

設計

// ...

效益 & 注意事項

效益

  1. 當我們依賴抽象 (介面/抽象類別) 而不是具體實現 (類別),可以透過一些單元測試的工具,很快做出假物件來對我們的功能做驗證。
    對於開發人員來說,不需要一開始就煩惱具體的實作是甚麼,而是可以更快地透過介面來驗證我們的功能設計是不是我們想要的。甚至可以在具體實現完成之前,對我們的功能進行驗證。(TDD = Test-Driven Development = 測試驅動開發)
  2. 抽象本身決定了要如何使用這個功能,只要這個介面是被確定的,不管具體實現是誰做的,如何做的,都不會跳脫出這個範疇,使用的人再也不用擔心因為具體實現類別變更,導致所有用到這個功能的地方都需要重新檢查有沒有被影響到。

注意事項

  1. 在小型項目中很難體會依賴反轉的優點,相較於使用介面,直接 new 出一個需要的物件更快更實際。
    只有當專案越來越大,參與的人員越來越多,才能感受到當需求不斷變更的狀況下,只有使用依賴反轉才能讓程式的穩健度提高,讓維運人員可以更加的容易地調整和擴展。
  2. 依賴反轉後,因為依賴的是抽象,那接下來的問題就是,應該透過甚麼機制,把真正的實體傳入,甚至應該要如何控制這個物件的生命週期,是開發人員必須要額外去 Survey 的內容。(ex: DI 框架)

Reference

設計模式之禪