You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
High level modules should not depend upon low level modules.Both should depend upon abstractions.
Abstractions should not depend upon details.Details should depend upon abstractions.
什么是依赖倒置原则(Dependence Inversion Principle)?
依赖倒置原则的原始定义:
高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
High level modules should not depend upon low level modules.Both should depend upon abstractions.
Abstractions should not depend upon details.Details should depend upon abstractions.
在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化;细节就实现类,实现接口或继承抽象而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字new产生一个对象。在Swift语言中,基本类似,只不过面向接口变成了面向协议,两者基本一致。
采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
下面我用一个例子来展现依赖倒置原则在提高代码的可读性和可维护性中所起的重要作用。还是先看看我们的UML图:
通过上面代码,我们实现了一个基本的司机开奔驰的场景。但是假如我们现在有辆宝马车类
BMW
,这个时候发现,Driver
类的drive
方法无法接收BMW
类。问题出现了,我们的Driver
类和Benz
之间是强耦合的,其导致的结果就是我们的系统可扩展性大大降低。还有一个问题,我们在团队协同开发的时候,假设Driver
类和Benz
类分别由两名开发人员来开发,就会发现Driver
类在Benz
类未实现之前,是无法实现drive
方法的,因为在drive
方法中调用了benz.run()
方法,两者有一定的依赖,这样就导致了两名开发人员无法协同开发,影响整体开发进度。现实中这种情况太多了,由于模块之间有很强的依赖和耦合,往往会导致多人无法正常协作。这个时候,依赖倒置原则就开始发挥作用了,下面我们来看看利用依赖倒置原则是如何来解决上述问题的。承接上面的例子,引入依赖倒置原则后的类图如下图所示:
我们建立了两个协议(接口):PDriver和PCar,分别定义了司机和汽车的智能,司机驾驶汽车,所以必须实现drive方法,汽车必须实现run方法。
上面是所有代码实现,我们遵循“抽象不应该依赖细节”,也就是我们认为抽象(PCar协议)不依赖
BMW
和Benz
两个实现类。下面再来看看我们的业务场景。
从上面的例子中,我们的业务逻辑并没有直接依赖具体的类,而是直接依赖抽象协议,BenzCar和BMWCar都遵循PCar协议(Java里面的interface)所以这里司机类的
drive
方法可以调用具体实现类的run
方法。从上面的代码也可以看出,无论汽车是什么类型,只要遵循PCar
协议,司机类NewDriver
就可以调用run
方法,低层模块BenzCar
或BMWCar
无论怎么变化,都不影响高层模块业务逻辑的实现。依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
依赖的三种写法
在类中通过构造函数声明依赖对象,按照依赖注入的说法,这种方式叫做构造函数注入。按照这种方式注入,
PDriver
和NewDriver
代码就可以修改为这样:在抽象中设置Setter方法声明依赖关系,按照依赖注入的说法,这种方式叫做Setter依赖注入。按照这种方式注入,
PDriver
和NewDriver
代码就可以修改为这样:在协议(或接口)的方法汇总声明依赖对象,前面用依赖倒置原则注入依赖的例子就是通过协议(或接口)声明依赖的方式。
总结
依赖倒置原则的本质是通过抽象(协议、接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松藕合,我们在项目中如何使用依赖倒置原则呢?只需要遵循下面几个规则:
在实际项目中,只要记住“面向协议(接口)编程”就基本上抓住了依赖倒置原则的核心
The text was updated successfully, but these errors were encountered: