[筆記] 依賴注入 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
9public class Mine
{
public Mcdonald mcdonald = new Mcdonald();
public void Eat()
{
mcdonald.Service();
}
}呼叫使用時
1
2Mine mine = new Mine();
mine.Eat();
小明
找外送公司
1
2
3
4
5
6
7
8
9
10
11
12private static IContainer MiddleCompany()
{
ContainerBuilder builder = new ContainerBuilder();
//在外送公司裡寫需求申請單
builder.RegisterType<MineWithMiddle>();
//小明所需麥當勞需求
builder.RegisterType<Mcdonald>().As<IService>();
return builder.Build();
}呼叫使用時
1
2
3
4
5
6IContainer middleCompany = MiddleCompany();
//外送公司自動幫小明注入一個營業中的麥當勞
MineWithMiddle mineWithMiddle = middleCompany.Resolve<MineWithMiddle>();
mineWithMiddle.Eat();