IoC 是什麼 ?
IoC 是一種設計原則,主要的用途是降低物件之間的耦合,特別是在建立物件的耦合關係。
為什麼要使用 IoC ?
系統為了運作,其中的物件必定有依賴關係,當系統越大越複雜,這些依賴關係也越來越嚴重。因此希望透過由外界提供(注入)物件而不是主動建立物件的方式來降低耦合關係。
如何使用 IoC ?
IoC 比較常見的方法為 DI (Dependency injection),而 DI 的具體實作有 Setter 注入,建構式注入,介面注入。以下使用範例來描述 DI 的具體實作。
當 Client 依賴於 Server,主動建立物件的方式就是使用 new 關鍵字建立需要的物件,如下在 Client 的建構式中建立了 Server 物件。
public class Client {
private Server mServer;
public Client() {
mServer = new Server();
}
}
Setter 注入就是提供一個公開的方法傳入 Server。
public void setServer(Server server) {
mServer = server;
}
建構式注入則是換成從建構式傳入 Server。
public Client(Server server) {
mServer = server;
}
介面注入會另外建立介面(IServer)並提供方法來傳入 Server。
public interface IServer {
public void setServer(Server server);
}
public class Client implements IServer {
private Server mServer;
@Override
public void setServer(Server server) {
mServer = server;
}
}
Simple Factory Pattern 簡單工廠模式
以上的三種注入方式適用於簡單的依賴情況。
若是產生依賴物件的過程較複雜,可以考慮套用工廠系列模式,一個非常簡單的簡單工廠如下
public class ServerFactory {
public static Server makeServer(){
return new Server();
}
}
而 Client 就從 ServerFactory 來取得 Server
public class Client {
private Server mServer = ServerFactory.makeServer();
}
乍看之下 ServerFactory 似乎只做了很簡單的工作,但這個工廠卻可以隔離產生Server 的變化對 Client 的影響。
首先是產生 Server 的變化
假設在系統中有大量產生 Server 的呼叫點(new Server()),但沒有工廠隔開。萬一因為需求變化導致 Server 的建構式需要改變(多傳入一個參數),就代表系統中所有產生 Server 的呼叫點都要修改。若是使用工廠,便可把變化封裝在工廠中。
第二是測試 Client 的難度
若 Server 本身是重量級物件,建立過程需要一堆繁瑣的過程或元件(如存取資料庫或網路元件等等)。那麼測試 Client 的難度會變得非常高,甚至無法測試。而透過 ServerFactory,可以很簡單的建立 MockServer 來測試 Client 的邏輯。
DI 框架
以上的描述都是屬於自己動手來建立 IoC 機制,這些方式對於簡單的依賴關係是足夠的。
但若情況再複雜一些,比如建立 Server 需要再建立 HttpConnection 物件而 HttpConnection 物件需要再建立 Authorization 物件,Authorization 物件又需要傳入 Account 物件…。
因為這些依賴關係之間層層相依且具有順序,靠手動方式建立 IoC 不僅容易出錯還需要寫出一堆樣板代碼,這種情況就可以考慮透過 DI 框架來自動管理。