IoC控制反轉理解
阿新 • • 發佈:2019-01-06
IoC(Inverse of Control),即控制反轉,也叫做依賴注入。是面向物件設計的一個重要的概念。它提出了將被呼叫物件的控制權由呼叫者轉移到第三方控制器上。這樣以滿足軟體開發中的依賴倒置(DI)原則。
一個電影為例:
《墨攻》中一片段:守城士兵問劉德華扮演的墨者革離“來者何人?”,革離回答說“墨者革離”。現在考慮這樣一個劇本:
可以看到,演員直接侵入了劇本之中,這樣假設不再由劉德華扮演革離,那麼劇本將不再適用。為此,我們實現一個革離的介面,通過介面展開劇情:
此時,我們在不經意間,已經完成了控制反轉:原本在指令碼(呼叫者)之中就要給定具體的演員(被呼叫者),此時,我們將演員的決定權交由導演(第三方控制器)決定。以上便是控制反轉的介紹。在實踐中,我們通常有三種方式實現控制反轉:
class Action{ public void gateAsk(){ //演員直接侵入劇本 LiuDeHua ldh=new LiuDeHua(); ldh.responseAsk(); } }
可以看到,演員直接侵入了劇本之中,這樣假設不再由劉德華扮演革離,那麼劇本將不再適用。為此,我們實現一個革離的介面,通過介面展開劇情:
class Action{
public void gateAsk(){
//引入介面展開劇情
GeLi geli=new LiuDeHua();
geli.responseAsk();
}
}
這樣的Action、LiuDeHua、GeLi關係如下:
但是我們可以看到,LiuDeHua還是出現在劇本之中,指令碼最終還是依賴於具體的扮演者。那麼如何才能讓Action指令碼與具體的扮演者無關呢?這時候我們可以考慮一個導演,讓他來控制GeLi的扮演者,即由導演決定GeLi的具體實現。如下:
- 建構函式注入
- 屬性注入
- 依賴注入
但是存在一個弊端就是,演員劉德華在指令碼開始拍攝時就一直在場。這顯然是不可取的(因為這會佔用計算機的記憶體)。所以一個好的方法是讓演員在有戲的地方出現: 2.屬性注入: 其實就是通過一個getter和一個setter完成對相關介面的實現類的傳入:class Action{ private GeLi geli; public Action(GeLi geli){ this.geli=geli; } public void gateAsk(){ //引入介面展開劇情 GeLi geli=new LiuDeHua(); geli.responseAsk(); } } public class Director{ GeLi geli=new LiuDeHua(); Action action=new Action(geli); action.gateAsk(); }
class Action{
private GeLi geli;
public Action(){}
//屬性注入
public void setGeLi(GeLi geli){
this.geli=geli;
}
public void gateAsk(){
//引入介面展開劇情
GeLi geli=new LiuDeHua();
geli.responseAsk();
}
}
public class Director{
GeLi geli=new LiuDeHua();
Action action=new Action();
action.setGeLi(geli);
action.gateAsk();
}
3.介面注入:
其實就是就是將所有依賴注入的方法集合到一個介面中,然後通過實現介面方法來實現介面實現類的傳入。
/**
* ActorArrange介面
*/
public interface ActorArrange {
public void setGeLi(GeLi geli);
}
class Action implements ActorArrange{
private GeLi geli;
public Action(){}
//屬性注入
public void setGeLi(GeLi geli){
this.geli=geli;
}
public void gateAsk(){
//引入介面展開劇情
GeLi geli=new LiuDeHua();
geli.responseAsk();
}
}
public class Director{
GeLi geli=new LiuDeHua();
Action action=new Action();
action.setGeLi(geli);
action.gateAsk();
}
這樣,我們成功地將控制權轉移到了Director上,使得Action只專注於拍攝。但是總得工作量並沒有減少啊!如何實現這些演員分配工作的自動化呢?由此,我們引入了第三方容器。它幫助完成類的初始化與裝配工作,讓開發者從這些底層實現類的例項化、依賴關係裝配等工作中脫離出來,專注於更有意義的業務邏輯開發工作。
本文轉自http://stamen.iteye.com/blog/1489223/,在此感謝原著作者。