您的位置:首页 > 其它

IoC控制反转理解

2017-05-13 16:14 204 查看
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的具体实现。如下:



此时,我们在不经意间,已经完成了控制反转:原本在脚本(调用者)之中就要给定具体的演员(被调用者),此时,我们将演员的决定权交由导演(第三方控制器)决定。以上便是控制反转的介绍。在实践中,我们通常有三种方式实现控制反转:
构造函数注入
属性注入
依赖注入
1.构造函数注入:
    在构造函数中将接口的实现类以参数的方式传入。例如:
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();
}

但是存在一个弊端就是,演员刘德华在脚本开始拍摄时就一直在场。这显然是不可取的(因为这会占用计算机的内存)。所以一个好的方法是让演员在有戏的地方出现:
2.属性注入:
    其实就是通过一个getter和一个setter完成对相关接口的实现类的传入:

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/,在此感谢原著作者。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息