IoC(Inversion of Control, 控制反转) 思想在现代框架设计中使用度越来越高。
IoC是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的实现方式叫做依赖注入(Dependency Injection,简称DI),还有一种实现方式叫“依赖查找”(Dependency Lookup)。
早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题。他总结出是依赖对象的获得被反转了,因为大多数应用程序都是由两个或是更多的类通过彼此的合作来实现业务逻辑,这使得每个对象都需要获取与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实现(如创建合作对象),那么这将导致代码高度耦合并且难以维护和调试。
IoC提出背景
以一个实例入手,简单介绍下IoC提出的原因。
假如class A 中用到了class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。示例代码如下:
interface IB {
void getData();
}
class B implemnts IB {
@Override
public void getData() {
system.out.println("DATA");
}
}
class A {
IB b;
String getData() {
b = new B();
b.getData();
}
}
从上述代码可知,类A依赖于类B,且在其内部创建了类B的一个实例。这种方式因为将B的实例创建耦合到了类A中,当需要使用IB接口的另一个实现时,就需要更改代码。
一种有效的缓解方式是使用工厂处理接口(如上述IB接口)的实现。示例代码如下:
interfaceBFactory {
public IB create(Object condition) {
if(condition == condA) {
return new B();
} else if(condition == condB) {
return new BB();
} else {
return new BBB();
}
}
}
使用工厂可以一定程度缓解类A对类B实例的创建的耦合,但实质上这种代码耦合并没有改变(转变成需要由工厂去创建接口的实例)。
为解耦上述依赖,IoC模式应运而生。IoC模式,通过构造的IoC容器把需要的接口实现绑定到需要它的类中,从而提高了代码的灵活性和可维护性。
IoC最基本的实现方式是“反射”。反射技术可以让应用在运行时动态决定生成哪一种对象。以Java为例,在过去,反射方式相对于正常的对象生成方式要慢十几倍。但后来,经过SUN改良优化后,通过反射生成对象和通常对象生成方式,速度已经相差不大了(但依然有一倍以上的差距)。
IoC分类
Interface Inversion
Flow Inversion
Creation Inversion
依赖注入(Dependency Injection)
依赖注入:组件不做定位查询,让容器去决定依赖关系。容器全权负责的组件的装配,它会把符合依赖关系的对象通过属性或者构造函数传递给需要的对象。
常见的依赖注入实现有三种:构造方法注入、setter方法注入、接口注入等。
(1) 构造方法注入:即被注入对象可以通过在其构造方法中声明依赖对象的参数列表,让外部(通常是IOC容器)知道它需要哪些依赖对象,然后IOC容器会检查被注入对象的构造方法,取得其所需要的依赖对象列表,进而为其注入相应对象。
(2) setter方法注入:即当前对象只需要为其依赖对象所对应的属性添加setter方法,IOC容器通过此setter方法将相应的依赖对象设置到被注入对象的方式即setter方法注入。
(3) 接口注入:被注入对象如果想要IOC容器为其注入依赖对象,就必须实现某个接口,这个接口提供一个方法,用来为被注入对象注入依赖对象,IOC容器通过接口方法将依赖对象注入到被注入对象中去。相对于前两种注入方式,接口注入比繁琐和死板,被注入对象必须声明和实现另外的接口。
依赖查找(Dependency Lookup)
容器提供回调接口和上下文条件给组件。EJB和Apache Avalon 都使用这种方式。组件必须使用容器提供的API来查找资源和协作对象,仅有的控制反转只体现在那些回调方法上:容器将调用这些回调方法,从而让应用代码获得相关资源。
参考
https://martinfowler.com/articles/injection.html Inversion of Control Containers and the Dependency Injection pattern
https://baike.baidu.com/item/控制反转 控制反转(百科)
https://blog.csdn.net/coderder/article/details/51897721 依赖注入
https://www.codeproject.com/Articles/542752/Dependency-Inversion-Principle-IoC-Container-Depen
https://blog.csdn.net/iycynna_123/article/details/52414104
原创不易,如果本文对您有帮助,欢迎关注我,谢谢 ~_~