依赖
依赖:在ClassA(调用者
)中初始化ClassB(被调用者
)的实例,那么ClassA对ClassB有一个依赖。
class ClassA {
var classB: ClassB
init() {
self.classB = ClassB()
}
}
依赖注入
依赖注入:ClassA(调用者
)非自己主动创建
ClassB(被调用者
)的实例,而是通过外部(第三方)完成ClassB的创建,然后注入到ClassA中,就称为依赖注入。
调用者不再直接创建依赖
,而是通过注入依赖
,持有被调用者。
class ClassA {
var classB: ClassB
init(classB: ClassB) {
self.classB = classB
}
}
控制反转
创建ClassB的工作不再由调用者ClassA来完成,而是借助第三方实现具体依赖关系的创建,ClassA创建ClassB由主动行为变成了被动行为,ClassA创建ClassB的控制权也因此由主动变被动,因此称为 控制反转。(Class也可以改为模块、组件等)

注入方式
注入方式:构造器注入、设值(setter)注入、接口注入。
构造器注入:
init(classB: ClassB) {
self.classB = classB
}
setter注入:
Swift: var classB: ClassB?
OC: @property (nonatomic, strong) ClassB *ClassB;
接口注入:
func injectClassB(classB: ClassB) {
self.classB = classB;
}
依赖注入解决的问题:
1.利于单元测试或者Mock测试。
2.解耦,将依赖之间进行解耦, 分离了调用方和被调用方。
3.无需在修改ClassB创建方式时,需要修改ClassA的代码,同时ClassA不用关心ClassB创建细节,只用关心ClassB提供的服务。
4.依赖变成抽象接口依赖提高扩展性。ClassC提供了ClassB类似服务,可以方便切换成ClassC。
5.通过NSClassFromStirng转换成同名的类,即反射机制实现运行时动态控制依赖对象的引入。
依赖反转(依赖倒置原则)
上层模块不应该依赖底层模块,上层和底层都应该依赖于抽象,上层模块定义并依赖抽象接口,底层模块实现该接口。
依赖未反转
/** 底层B*/
public class ModuleB {
public func setup() {
}
}
let moduleManager = ModuleManager()
let moduleB = ModuleB()
moduleManager.setModuleB(module: moduleB)
// 如果新增了ModuleC 还需要在moduleManager中新增方法setModuleC,如下:
let moduleC = ModuleC()
moduleManager.setModuleC(module: moduleC)
依赖反转
/** 定义模块接口*/
protocol ModuleProtocol {
func setup()
}
/** 底层B*/
public class ModuleB: ModuleProtocol {
public func setup() {
}
}
/** 底层C*/
public class ModuleC: ModuleProtocol {
public func setup() {
}
}
/** 高层*/
class ModuleManager {
// 注册单个module
func setModule(moudle: ModuleProtocol) {
moudle.setup()
}
// 注册多个module
func setModules(modules: [ModuleProtocol]) {
for module in modules {
module.setup()
}
}
}
var moduleManager = ModuleManager()
let moduleB = ModuleB()
moduleManager.setModule(module: moduleB)
新增底层模块ModuleC时,高层模块A不需要写兼容代码。
let moduleC = ModuleC()
moduleManager.setModule(module: moduleC)
依赖倒置指导接口隔离原则,最终目标是为了实现开闭原则
,高层模块不用修改,对底层扩展开放,我们很容易新增、替换、删除底层模块,利于组件化。

依赖注入的框架objection
参考资料:
https://www.jianshu.com/p/dabca5ab1a80
https://mp.weixin.qq.com/s/Zp-OqCVVr9CbDv1Y1zWN-w
https://github.com/android-cn/blog/tree/master/java/dependency-injection
https://baike.baidu.com/item/%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/5177233?fr=aladdin
网友评论