依賴注入

軟件工程中,依賴注入(dependency injection,縮寫為 DI)是一種軟件設計模式,也是實現控制反轉的其中一種技術。這種模式能讓一個物件接收它所依賴的其他物件。「依賴」是指接收方所需的對象。「注入」是指將「依賴」傳遞給接收方的過程。在「注入」之後,接收方才會調用該「依賴」[1]。此模式確保了任何想要使用給定服務的物件不需要知道如何建立這些服務。取而代之的是,連接收方物件(像是 client)也不知道它存在的外部代碼(注入器)提供接收方所需的服務。

註:編程語言層次下,「接收方」為對象和 class,「依賴」為變量。在提供服務的角度下,「接收方」為客戶端,「依賴」為服務。

該設計的目的是為了分離關注點,分離接收方和依賴,從而提供鬆耦合以及代碼重用性

傳統編程方式,客戶對象自己創建一個服務實例並使用它。這帶來的缺點和問題是:

  • 如果使用不同類型的服務對象,就需要修改、重新編譯客戶類。
  • 客戶類需要通過配置來適配服務類及服務類的依賴。如果程序有多個類都使用同一個服務類,這些配置就會變得複雜並分散在程序各處。
  • 難以單元測試。本來需要使用服務類的 mock 或 stub,在這種方式下不太可行。

依賴注入可以解決上述問題:

  • 使用接口或抽象基類,來抽象化依賴實現。
  • 依賴在一個服務容器中註冊。客戶類構造函數被注入服務實例。框架負責創建依賴實例並在沒有使用者時銷毀它。

概念

依賴注入涉及四個概念:

  • 服務:任何類,提供了有用功能。
  • 客戶:使用服務的類。
  • 接口:客戶不應該知道服務實現的細節,只需要知道服務的名稱和 API。
  • 注入器:Injector,也稱 assembler、container、provider 或 factory。負責把服務引入給客戶。

依賴注入把對象構建與對象注入分開。因此創建對象的 new 關鍵字也可消失了。

實現方式

  • 建構子注入:依賴由客戶對象的構造函數傳入。
  • Setter 注入:客戶對象暴露一個能接收依賴的 setter 方法。
  • 接口注入:依賴的接口提供一個注入器方法,該方法會把依賴注入到任意一個傳給它的客戶。客戶實現一個setter接口,可設置依賴。

參考資料

  1. ^ James Shore: Dependency Injection Demystified. www.jamesshore.com. [2020-02-06]. (原始內容存檔於2020-06-30).