筆記 - 依賴注入 DI、控制反轉 IoC、依賴反轉原則 DIP

[筆記] 依賴注入 DI、控制反轉 IoC、依賴反轉原則 DIP

DI is about wiring, IoC is about direction, and DIP is about shape.

  • 依賴注入 ( Dependency Injection ) : 為一種設計模式,將依賴通過注入的方式提供給需要的 class,是 IoC 與 DIP 的具體表現

  • 控制反轉 ( Inversion of Control ) : 為一種思想,函式主要功能之外的其他功能應該由第三方完成

  • 依賴反轉原則 ( Dependency-Inversion Principle ) : 為一種思想,較高層次的模組不應該依賴較低層次的被模組,應該提供接口讓較低層次的模組實現

  • 目的都是為了解偶,使程式好維護,且更容易測試

依賴反轉原則

  • 原則 :

    • 高階模組不該依賴於低階模組,兩者都該依賴抽象
    • 抽象不依賴具體實作方式,具體實作方式則依賴抽象
  • 雖然透過依賴反轉原則可以改變依賴於抽象,但程式上還是必須 new 出 instance,就是呼叫者對依賴的控制流程有主導權

  • 這樣若更換低階模組,還是必須是調整高階模組 new XXX()
  • 這時就要使用到控制反轉

控制反轉

  • 原則 :

    • 把對於某個物件的控制權移轉給第三方容器
  • 例如 :

    • A 物件內部需要使用 B、C 物件,那 B、C 與 A 就有耦合,A 控制著 B、C
    • 控制反轉是把 A 對 B、C 的控制權轉交第三方容器
    • 降低 A 與 B、C 間的耦合,都依賴於第三方容器

  • 原本的關係圖

  • 使用控制反轉後的關係圖

  • 與好萊塢法則一致 :

Don’t call me, I’ll call you.

依賴注入

  • 為實現依賴反轉原則與控制反轉的其中一種設計模式
  • 把被依賴物件注入被動接收物件中

  • 小明 是個喜歡叫麥當勞的人,所以他每天都會打給 他家附近的麥當勞 叫麥當勞來吃

    • 若是有天 他家附近的麥當勞 公休了,那小明就要另外再找麥當勞,由此可知小明耦合他家附近的麥當勞
  • 如果今天 小明 是把他的要求給 外送公司,那麼 外送公司 就會幫他尋找有沒有營業中的麥當勞,若是 他家附近的麥當勞 公休了,外送公司 就會自動找另一間營業中的麥當勞

    • 原本 小明 需耦合於 他家附近的麥當勞,現在被 外送公司 做了控制反轉,由 外送公司 來提供麥當勞
    • 小明 不用管 他家附近的麥當勞 是否公休,外送公司 會幫他找到營業中的麥當勞
  • 小明 可看作被動接收物件

  • 他家附近的麥當勞 可看作被依賴物件
  • 外送公司 可看作 IoC 容器

程式碼

  • 小明 自己依賴於 他家附近的麥當勞

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Mine
    {
    public Mcdonald mcdonald = new Mcdonald();

    public void Eat()
    {
    mcdonald.Service();
    }
    }
    • 呼叫使用時

      1
      2
      Mine mine = new Mine();
      mine.Eat();
  • 小明外送公司

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private static IContainer MiddleCompany()
    {
    ContainerBuilder builder = new ContainerBuilder();

    //在外送公司裡寫需求申請單
    builder.RegisterType<MineWithMiddle>();

    //小明所需麥當勞需求
    builder.RegisterType<Mcdonald>().As<IService>();

    return builder.Build();
    }
    • 呼叫使用時

      1
      2
      3
      4
      5
      6
      IContainer middleCompany = MiddleCompany();

      //外送公司自動幫小明注入一個營業中的麥當勞
      MineWithMiddle mineWithMiddle = middleCompany.Resolve<MineWithMiddle>();

      mineWithMiddle.Eat();

参考

tags: 筆記 依賴注入 DI 控制反轉 IoC 依賴反轉原則 DIP
Author: Kenny Li
Link: https://kennyliblog.nctu.me/2019/09/09/Dependency-Injection-Inversion-of-Control-Dependency-Inversion-Principle/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.