在前文物件導向設計原則—SOLID,我們簡單的回顧 Robert.C.Martin 提出的 SOLID 原則,單一職責、開放封閉、里氏替換、接口隔離以及依賴反轉。
其中,依賴反轉(Dependency inversion principle, DIP)是筆者認為相當重要的原則,實務上使用的機率相當的高,不管是單元測試的實作,功能模組的替換。
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
高階模組不應該依賴於低階模組,兩者都該依賴抽象。
B. Abstractions should not depend on details. Details should depend on abstractions.
抽象不應該依賴於具體實作方式。具體實作方式則應該依賴抽象。
這兩條定義,說白一點,類別中,不應該直接使用另一個具有實作類別,而是使用抽象的介面,去承接繼承該介面的實作類別。它的目標就是解除物件與物件間,兩者的直接相依關係。
光看文字說明,就跟天書一樣,所以下面用一些例子來說明。
public class ReportStatistic()
{
private SQLAccess _access = new SQLAccess();
public double Sum()
{
var items = _access.GetAllCost();
...
}
}
public class SQLAccess
{
public List<CostItem> GetAllCost()
{
...
}
}
從上面的程式碼可以看到,ReportStatistic (高階模組)緊緊依賴與 SQLAccess (低階模組),筆者習慣稱這種情況為高耦合。
當我們依據 DIP 的原則,將兩個物件均改為依賴抽象,那麼程式碼會變成……
public class ReportStatistic()
{
private IAccess _access = new SQLAccess();
public double Sum()
{
var items = _access.GetAllCost();
...
}
}
public interfalce IAccess
{
List<CostItem GetAllCost();
}
public class SQLAccess : IAccess
{
public List<CostItem> GetAllCost()
{
...
}
}
雖然,我們使用抽象介面 IAccess 來承接低階模組 SQLAccess,達到使用依賴反轉,解決高階模組直接依賴低階模組的情況。但是,假若有一天,我們要替換低階模組,只好去變動原本程式碼,去達到替換的目標。
在上面的程式碼,可以猜到資料來源是使用 SQLAccess 這個類別,但是,如果今天有需求要求要從 csv 存取資料,我們也依據 DIP 原則,繼承 IAccess 實作了一個 CsvAccess。那程式碼應該會變成……
public class ReportStatistic()
{
private IAccess _access = new CsvAccess();
public double Sum()
{
var items = _access.GetAllCost();
...
}
}
public class CsvAccess : IAccess
{
public List<CostItem> GetAllCost()
{
...
}
}
這就很明顯的違背開放封閉原則了,那麼……要在不變動原本程式碼的前提下,去達到替換低階模組的目標,要怎麼做呢?
於是乎,就有人想到,那麼就不要讓高階模組,自行控制低階模組的建立。而是**將低階模組建立的控制權移到高階模組外部。**再將建立好的低階模組放到高階模組中,讓高階模組使用。
public class ReportStatistic()
{
private IAccess _access = null
ReportStatistic(IAccess access)
{
_access = access;
}
public double Sum()
{
var items = _access.GetAllCost();
...
}
}
這種方式,就是我們常說的控制反轉(Inversion of Control ,IoC) 與依賴注入(Dependency Injection, DI) 這兩個名詞。
針對依賴反轉、控制反轉、依賴注入這個主題,筆者盡可能將自己所知的寫出來,但深深覺得還有許多的不足。
不過,己經許多前輩,針對這個主題撰寫許多很優良的文章,分享給大家。筆者將自己知道的文章連結分享於下方,讓各位看倌可以更深入的了解依賴反轉。