Back

Dependency Injection 與工廠模式的結合(1)

Dependency Injection 簡介

Dependency Injection 是一種物件改變耦合的一種設計概念,通常會跟 IOC(Inversion Of Control) 一起談

以下一個簡單的注入範例

範例

故事

父母今天要教育小孩科目,但一對父母並不是只會擁有一個小孩,可能會有多個。因此我們把小孩當作參數傳給教育小孩這個方法,使其變得有彈性。

方法中注入小孩其實就是 方法注入(Method Injection)

創建小孩的過程會注入一個姓名,這種注入方式就是 建構式注入(Constructor Injection)

透過物件設定值的方式,就是 屬性注入(Property Injection)

Struct

public interface IParent {
  void TeachChild (IClild child, Subject string);
}

public class Parent: IParent {
  public Parent () { }

  public void TeachChild (IClild child, string subject ) {
    Console.WriteLine($"Teach {child.GetName} about ${subject}")
  }
}

public interface IChild {
  string GetName ();
  void SetAge(int age);
}

public class Child {
  private string _childName;
  private int _age;
  public Child (string name) {
    this._childName = name;
  }

  public string GetName() {
    return this._childName;
  }

  public void SetAge(int age) {
    this._age = age;
  }
}

.NET 的特別之處

當我們知道 DI 之後,就要來細講 NET 的 DI 概念了

在 NET 的架構下,會建議改用框架預設的 IServiceCollection(IServiceProvider)

來取代手動 DI ,而透過 IServiceProvider 取出來的物件

概念如下圖

先將所有的 Service 註冊到資料提供中心,如果有其他物件需要就在從資料提供中心中取出來

這樣的好處是 Service 跟 其他物件的耦合性,會變成是跟資料提供中心耦合(詳細概念可參考前篇的AbstractClass比較Interface )

而在 Service 註冊的時候,會有三種特性,這三種特性會改變資料提供中心對外的時候,是否要產生新的物件(生命週期)給需求者,分別是

  • Singleton: 在 APP 的生命週期中,只會存在一個實例,因此每次取回都是相同的記憶體位置
  • Scoped: 在一個 Requeset 的過程中僅在第一次建立新的實例,第二次開始會取得與第一次同樣的實例
  • Transient:每次要都取回一個新的實例

結語

透過 DI 的方式可以解決物件之間高耦合的問題,以利未來要做調整或抽象會更加簡單,而下一篇再來說明怎麼透過原生的 DI Pull 達成工廠模式

參考資料

NETDI