IoC & DI

Dependency Injection 依賴注入 (DI)

參考資料:Dependency Injection 筆記(https://www.huanlintalk.com/post/2011-10-14-dependency-injection-1/)

如何向五歲的孩童解釋 DI?

該帖的問題是:「如何向五歲的孩童解釋 DI?」在眾多回答中,有位名叫 John Munch 的仁兄假設提問者就是那五歲的孩童而給了如下答案:

當你自己去開冰箱拿東西時,很可能會闖禍。
你可能忘了關冰箱門、可能會拿了爸媽不想讓你碰的東西,
甚至冰箱裡根本沒有你想要找的食物,又或者它們早已過了保存期限。
你應該把自己需要的東西說出來就好,
例如:「我想要一些可以搭配午餐的飲料。」
然後,當你坐下用餐時,我們會準備好這些東西。

物件導向設計原則

SRP(Single Responsibility Principle):單一責任原則。一個類別應該只有一個責任。

OCP(Open/Closed Principle):開放/封閉原則。對開放擴充,對修改封閉。

LSP(Liskov Substitution Principle):里氏替換原則。物件應該要可以被它的子類別的物件替換,且完全不影響程式的既有行為。

ISP(Interface Segregation Principle):介面隔離原則。多個規格明確的小介面要比一個包山包海的大型介面好。

DIP(Dependency Inversion Principle):相依反轉原則。依賴抽象型別,而不是具象型別。

Inversion of Control 控制反轉(IoC)

一般的做法: 上層呼叫某個高階模組的方法,該方法 new 一個低階模組的物件出來用。 這樣這個方法就會綁定這個物件。

但如果有多種類似的物件呢?

利用 介面(interface) 來解耦,將這些類別抽象化(共通的部分抽出來,做成介面),使這些共通性成為規格,而那些物件再實作這個介面、實作這些規格。

DIP: 高階模組不應依賴低階模組,它們應該去相依抽象層。 抽象層不應依賴實作細節,而是實作細節去依賴抽象層。

之後在使用時,由於不能new 出介面,那麼物件從何而來? 答案是由上方 new 出想要的物件,傳到該方法去讓底部使用。

原本在底部 new 物件出來,改成了從上層傳物件到底部去用,所以控制反轉了。

Dependency Injection 依賴注入 (DI)

一種設計模式和原則,用來寬鬆耦合。

以上方舉例來說,由呼叫端將相依物件透過建構函式,注入至另一個物件的作法,是DI的一種常見寫法,叫作「建構式注入」(Constructor Injection)。

DI的三種注入方式: 1.建構式注入(Constructor Injection) 2.屬性注入(Property Injection) 3.方法注入(Method Injection)

Note: 每當需要注入相依物件時,一般建議優先考慮「建構式注入」,因為其用法對呼叫端來說相當明確、直覺——建立物件時就要一併傳入所有相依物件,所以呼叫端透過建構函式便可得知某物件相依於哪些第三方元件。

介面導向設計

原本相依的物件,現在都透過相依於介面。

當要測試時,再從外部將實作介面的測試物件傳入,去驗證其商業邏輯。

這個把初始化動作,由原本目標物件內,轉移到目標物件之外,稱作「控制反轉」,也就是 IoC。

這個把依賴的物件,透過目標物件公開建構式,交給外部來決定,稱作「依賴注入」,也就是 DI。

而 IoC 跟 DI,其實就是同一件事:讓外部決定目標物件的相依物件。

而這個介面,也可以是目標物件的擴充點,或是接縫。

Last updated