Thinking系列,旨在利用10分钟的时间传达一种可落地的编程思想。
IOC
系统中,经常会出现 A 模块,依赖 B 模块,同时也依赖 C 模块的情况。我们通常的处理方式是将 B、C 模块直接引入到 A 模块中,这个获取过程都在 A 模块中实现,随着业务的扩充,A 模块可能还需要 D、E、F… 等等模块,这将导致代码高度耦合并且难以维护和调试。且未来想要删除某模块,需要删除模块的代码,同时需要删除在 A 模块中的引用。
IOC(Inversion Of Control):控制反转
组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。
- 高层次的模块不应该依赖于低层次的模块,应该依赖于抽象;
- 抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
其背后的核心思想:针对接口编程,不针对实现编程!接口驱动,使得其可以供不同灵活的子类实现
实现
IOC 有两种实现方式:依赖查找和依赖注入。
依赖查找(Dependency Lookup):容器提供接口和上下文条件给组件,组件需要实现接口,该接口提供了一个对象,可以重用这个对象查找依赖。
依赖注入(Dependency Injection):内置对象是通过注入的方式进行创建。依赖注入有两种实现方式:Setter方式(传值方式)和构造器方式(引用方式)。
现实问题陈述
页面刷新,刷新按钮隶属于 Header 模块,页面 A 中点击刷新按钮。
常规思路:需要再 Header 中依赖 A 页面,然后调用 A 模块的刷新方法。这里 Header 模块属于高层模块 ,A 页面属于低层模块。
现在如果需要在 B 页面增加刷新,则 Header 同时也要依赖 B 模块。整个流程会非常复杂,随着业务扩大,整体模块耦合度也会很大。
解决方案
将 Header 模块修改为依赖接口,页面 A 和 页面 B 各自实现接口。大大降低了 Header 模块的修改几率。
Header 模块
这里我们抽象了接口 init
方法,每个模块各自实现 init()
即可。
A 模块
典型IOC的实现(伪代码)
优势:模块之间靠接口规则约束,完全解耦。增加模块只需按要求注册和提供相关 refresh 方法即可;未来想删除 B 模块,同样只需将 B 模块代码删除即可,Header和Container模块无需做任何修改!
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net