周末随笔-聊一聊IOC和DI
2017-09-09 15:06
176 查看
首先,本文探讨的目的是如何让系统的扩展性变高,以实现降低迭代成本。追求开发速度的完全不必理会。
让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入,以移除调用类对某一接口实现类的依赖。
“依赖注入”显然比“控制反转”更好理解。
可以看到,类B的功能依赖于A,而且这里使用了组合。
当然,使用组合要比让B继承A并进行扩展好得多,这不是今天要讨论的。
这个例子的问题在于:B依赖的A由B构建。看起来好像没什么问题,但是:
B负责了A的创建,不符合SRP 单一职责原则。
当A业务扩展时,可能构造函数 发生改变,这样就要修改B的构造函数,不符合OCP 开闭原则
如果不面向接口编程的话,这个代码会更加糟糕,为了后面方便,这里已经提出了接口I(以减少本文的注意力分散)
倘若业务发展,B需要有子类时,很大可能是重构,(因为很大可能不符合里氏代换原则,就不往下讨论了)。
这就是大家说的耦合变高了。
按照IoC或者DI来构建代码,可以减少这样的问题。
setter方法注入
接口注入
注解注入
这样选择控制权已经不再属于B(IoC想描述的),一种注入形式实现了依赖对象的获得(DI想描述的)。
上面接口名字定的不好,暂不修改了
和setter注入差别不大,但是当接口I的客户有多个而且没有继承关系或者兄弟关系时,使用接口注入效果会更好一点,代码整体的可读性会好一点。
Android中使用较多的是Dagger/Dagger2.本篇就先不扩展了。
往往实际情况是:更多的注意力在界面、交互上,业务部分没有那么庞大,某一种业务的客户可能只有一个,即使当前的设计耦合高了不利于扩展,但根本没有矛盾爆发的机会。
IoC 控制反转
IoC(Inverse of Control),控制反转,但这个说法不够直白,在实际生产中,用控制转移来描述反而地道一点。今天不抠字眼,对象的控制权转交给第三方,往往就是:某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定。 但还是很难理解。DI 依赖注入
随后Martin Fowler提出了DI(Dependency Injection)依赖注入的概念用以代替IoC,即:让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入,以移除调用类对某一接口实现类的依赖。
“依赖注入”显然比“控制反转”更好理解。
看一个例子
interface I { void foo(); class A implements I{ public A() { //... } //... } class B { I i; public B() { i = new A(); //... } public void bar() { } }
可以看到,类B的功能依赖于A,而且这里使用了组合。
当然,使用组合要比让B继承A并进行扩展好得多,这不是今天要讨论的。
这个例子的问题在于:B依赖的A由B构建。看起来好像没什么问题,但是:
B负责了A的创建,不符合SRP 单一职责原则。
当A业务扩展时,可能构造函数 发生改变,这样就要修改B的构造函数,不符合OCP 开闭原则
如果不面向接口编程的话,这个代码会更加糟糕,为了后面方便,这里已经提出了接口I(以减少本文的注意力分散)
倘若业务发展,B需要有子类时,很大可能是重构,(因为很大可能不符合里氏代换原则,就不往下讨论了)。
这就是大家说的耦合变高了。
按照IoC或者DI来构建代码,可以减少这样的问题。
依赖注入的方式
构造函数注入setter方法注入
接口注入
注解注入
构造函数注入
class B { I i; public B(I i) { this.i = i; } }
这样选择控制权已经不再属于B(IoC想描述的),一种注入形式实现了依赖对象的获得(DI想描述的)。
setter方法注入
class B { I i; public B() { } public void setI(I i) { this.i = i; } }
接口注入
定义注入接口:上面接口名字定的不好,暂不修改了
interface InjectDependencyI { void setI(I i); } class B implements InjectDependencyI { I i; public B() { } public void setI(I i) { this.i = i; } }
和setter注入差别不大,但是当接口I的客户有多个而且没有继承关系或者兄弟关系时,使用接口注入效果会更好一点,代码整体的可读性会好一点。
注解注入
显然,这里存在一个IoC容器,按照规则帮我们进行一定的自动化处理,减少了手动注入的工作,而这些规则是使用注解描述的。Android中使用较多的是Dagger/Dagger2.本篇就先不扩展了。
写在最后
为什么在Android客户端工作中我们比较难体会到IoC/DI的作用呢?往往实际情况是:更多的注意力在界面、交互上,业务部分没有那么庞大,某一种业务的客户可能只有一个,即使当前的设计耦合高了不利于扩展,但根本没有矛盾爆发的机会。
相关文章推荐
- Spring随笔(IOC/DI 及注入方式)
- 聊一聊PHP的依赖注入(DI) 和 控制反转(IoC)
- Spring--IoC和DI
- 详解Spring IOC 与 DI 核心原理
- ioc(控制的反转) 和di(依赖注入)
- springIoCAndDI
- 控制反转(IOC)和依赖注入(DI)
- 在X++中使用IoC/DI模式应对不断变化的客户需求
- DI 和 IOC
- IOC和DI的区别
- 控制反转与依赖注入(IOC和DI)
- Spring应用(一) IOC和DI总结
- 转:控制反转(IoC)与依赖注入(DI)
- 对IOC/DI的理解(转载自开涛的博客)
- 依赖注入(DI) 与 控制反转(IOC)
- Spring基础-1-IOC与DI
- 控制反转(IoC)与依赖注入(DI)
- (二)Spring的IOC&DI概述
- 对DIP、IoC、DI、IoC容器的解释,静下心,认真看完就能理解
- 设计模式之初识IoC/DI(六)