Software Design - Principle - Inversion of Control (IoC)

反轉了什麼 ?

依賴對象的獲得被反轉了

在應用程式中設計總會有多個單元需要合作的情況,這時就會有配置依賴的需求,但這個配置應該由需求方來處理嗎?

讓依賴需求方自己處理最簡單的方式就是實例化(new),但這可能會有以下問題:

  • 不同需求方重複 new 是否會有浪費的問題? 能被共用嗎? 方便共用嗎?
  • 到處 new 來 new 去,依賴的管理變得很亂

那不如找一個單位負責來處理依賴配置。我不自己 new,而是別人 new 完後(注入給我/讓我查找),這麼所帶來的好處:

  • 資源複用更方便: 統一由容器創建或保存對象,不需要每個需求方都自己 new 一個新的。
  • 建造/使用分離: 依賴需求方操作其依賴項來完成任務才是他主要的責任,如果還要處理依賴項的實例化,責任就模糊了,因此將依賴項的創建和配置的控制權交給 IoC Container。

為此需要有一個 IoC Container 來處理,通常容器包含以下操作:

  • Register:註冊類型和依賴關係
  • Resolve:創建並註入依賴關係
  • Dispose:管理生命週期

實踐方式

最常見的方式分別是 依賴注入(Dependency Injection,DI)與 依賴尋找(Dependency Lookup)。

依賴尋找

可以簡單理解為 依賴需求方 « 主動 » 使用容器來取得依賴。依賴需求方直接使用 Locator.Resolve 取得依賴,但這種作法有些爭議(反模式),依賴需求方是不是有註冊的項目都能任意取得阿 ?

Service Locator 服務定位器是依賴尋找的典型實作。

依賴注入

透過注入依賴項讓 依賴需求方 « 被動 » 使用容器來取得依賴,常透過三種方式注入。

  • 建構子(推薦)
  • 屬性
  • 方法

權限相對清晰(建構子注入),能用依賴項的都在建構子給你了,不過你要額外new 其他東西也是沒人攔得住。

這個方式通常透過框架來處理,此外依賴需求方是不知道容器的存在(理想狀態,但有時會需要一些注入標記)。