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 其他東西也是沒人攔得住。
這個方式通常透過框架來處理,此外依賴需求方是不知道容器的存在(理想狀態,但有時會需要一些注入標記)。