控制反转与依赖注入
看到一个对这个概念很好诠释的帖子,特转发过来供大家一起学习 转载地址http://www.iteye.com/topic/692793 ? ?IoC——Inversion of Control? 控制反转
??????? 下面就来简要的回答一下上述问题,把这些问题搞明白了,IoC/DI也就明白了。 ??????? 一般有三方参与者,一个是某个对象;一个是IoC/DI的容器;另一个是某个对象的外部资源。 ????????当然是某个对象依赖于IoC/DI的容器 ????????对象需要IoC/DI的容器来提供对象需要的外部资源 ????????很明显是IoC/DI的容器 注入 某个对象 ????????就是注入某个对象所需要的外部资源 ????????当然是IoC/DI的容器来控制对象了 ????????主要是控制对象实例的创建 ??????? 反转是相对于正向而言的,那么什么算是正向的呢?考虑一下常规情况下的应用程序,如果要在A里面使用C,你会怎么做呢?当然是直接去创建C的对象,也就是说,是在A类中主动去获取所需要的外部资源C,这种情况被称为正向的。那么什么是反向呢?就是A类不再主动去获取C,而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中。 ??????? 用图例来说明一下,先看没有IoC/DI的时候,常规的A类使用C类的示意图,如图7所示: ????????????????????????????????????? 图7? 常规A使用C示意图 当有了IoC/DI的容器后,A类不再主动去创建C了,如图8所示: ???????????????????????????????????? 图8? A类不再主动创建C ????????????????????????????????????????????? ?图9? 有IoC/DI容器后程序结构示意图 ??????? 其实IoC/DI对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC/DI容器来创建并注入它所需要的资源了。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 关于控制反转和依赖注入的文章和书籍很多,对其定义也解释的也仁者见仁,这里就不赘述了,这是本人(只代表个人观点)理解之后用通俗的例子和平淡的话词为您解释,希望对您有所帮助: 控制反转(IoC/Inverse?Of?Control):?? 调用者不再创建被调用者的实例,由spring框架实现(容器创建)所以称为控制反转。 依赖注入(DI/Dependence?injection)?:?? 容器创建好实例后再注入调用者称为依赖注入。 当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例,。如果创建被调用者实例的工作不再由调用者来完成,而是由外部容器完成,因此称为控制反转;?创建被调用者?实例的工作通常由外部容器来完成,然后注入调用者,因此也称为依赖注入。 下面一个小实例: 定义一个接口? public interface Person { 第一个实现类: public class Chinese implements Person { 第二个实现类:? public class American implements Person { ???? public void sayHello() { } ? 注意这个类与传统设计有什么区别:该类调用Person子类的方法,传统设计在本类中创造实例,而在此类里并没有创造实例 public class User { //调用person子类重写的sayHello方法,这里的p并没有实例化 ??? public void function(){ } ? 外部‘容器’ public class Container{ ??? public static?User getBean(){??? ??????? Person p=new Chinese(); ?????? ?User user = new User(); ???????? //由容器‘注入’实例 ?????? ?user.setP(p); ??????? return user; ??? } } ? 测试类: public class Test{ ??? public static void main(String[] args){ ?????????? User user = Container.getBean(); ?????????? user.function(); ??? } } //后台输出‘您好’ 通过这个例子应该看懂了控制反转,和依赖注入了吧,这个是不是与传统设计相‘反了’。:-D ? ? 相关知识 ????? 依赖和耦合(Dependency?and?Coupling) ???????? 如果模块A调用模块B提供的方法,或访问模块B中的某些数据成员(当然,在面向对象开发中一般不提倡这样做),我们就认为模块A依赖于模块B,模块A和模块B之间发生了耦合。 那么,依赖对于我们来说究竟是好事还是坏事呢? 由于人类的理解力有限,大多数人难以理解和把握过于复杂的系统。把软件系统划分成多个模块,可以有效控制模块的复杂度,使每个模块都易于理解和维护。但在这种情况下,模块之间就必须以某种方式交换信息,也就是必然要发生某种耦合关系。如果某个模块和其它模块没有任何关联(哪怕只是潜在的或隐含的依赖关系),我们就几乎可以断定,该模块不属于此软件系统,应该从系统中剔除。如果所有模块之间都没有任何耦合关系,其结果必然是:整个软件不过是多个互不相干的系统的简单堆积,对每个系统而言,所有功能还是要在一个模块中实现,这等于没有做任何模块的分解。 因此,模块之间必定会有这样或那样的依赖关系,永远不要幻想消除所有依赖。但是,过强的耦合关系(如一个模块的变化会造成一个或多个其他模块也同时发生变化的依赖关系)会对软件系统的质量造成很大的危害。特别是当需求发生变化时,代码的维护成本将非常高。所以,我们必须想尽办法来控制和消解不必要的耦合,特别是那种会导致其它模块发生不可控变化的依赖关系。依赖倒置、控制反转、依赖注入等原则就是人们在和依赖关系进行艰苦卓绝的斗争过程中不断产生和发展起来的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |