依赖倒置原则
一.依赖倒置原则的定义
依赖倒置原则,英文缩写DIP,全称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。
官方翻译:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
还有一种定义:针对接口编程,不要针对实现编程。
举例来说:
Figure1中,高层对象A依赖于底层对象B的实现;
Figure2中,把高层对象A对底层的需求抽象为一个接口A,底层对象B实现了接口A,这就是依赖反转。
二.对依赖倒置原则的分析
对依赖倒置原则进行分析,我们可以发现其包含了三层含义:
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
- 抽象不应该依赖细节;
- 细节应该依赖抽象。
高层模块和低层模块容易理解,每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。那什么是抽象,什么又是细节呢?在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字new产生一个对象。依赖倒置原则在Java语言中的表现就是:
- 模块间的依赖是通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
- 接口或抽象类不依赖于实现类;
- 实现类依赖接口或抽象类。
依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
我们以下图为例来用代码来实现依赖倒置原则:
1 //将司机模块抽象为一个接口 2 public interface IDriver { 3 //是司机就应该会驾驶汽车 4 public void drive(ICar car); 5 } 6 7 public class Driver implements IDriver{ 8 //司机的主要职责就是驾驶汽车 9 public void drive(ICar car){ 10 car.run(); 11 } 12 } 13 14 //将汽车模块抽象为一个接口:可以是奔驰汽车,也可以是宝马汽车 15 public interface ICar { 16 //是汽车就应该能跑 17 public void run(); 18 } 19 20 public class Benz implements ICar{ 21 //汽车肯定会跑 22 public void run(){ 23 System.out.println("奔驰汽车开始运行..."); 24 } 25 } 26 27 public class BMW implements ICar{ 28 //宝马车当然也可以开动了 29 public void run(){ 30 System.out.println("宝马汽车开始运行..."); 31 } 32 } 33 34 //高层模块 35 public class Client { 36 public static void main(String[] args) { 37 IDriver xiaoLi = new Driver(); 38 ICar benz = new Benz(); 39 //小李开奔驰车 40 xiaoLi.drive(benz); 41 } 42 }
在新增低层模块时,只修改了高层模块(业务场景类),对其他低层模块(Driver类)不需要做任何修改,可以把"变更"的风险降低到最低。在Java中,只要定义变量就必然有类型,并且可以有两种类型:表面类型和实际类型,表面类型是在定义时赋予的类型,实际类型是对象的类型。就如上面的例子中,小李的表面类型是IDriver,实际类型是Driver。
三.依赖倒置原则的作用
依赖倒置原则的目的是把高层次组件从对低层次组件的依赖中解耦出来,这样使得重用不同层级的组件实现变得可能。把高层组件和低层组件划分到不同的包/库(在这些包/库中拥有定义了高层组件所必须的行为和服务的接口,并且存在高层组件的包)中的方式促进了这种解耦。由于低层组件是对高层组件接口的具体实现,因此低层组件包的编译是依赖于高层组件的,这颠倒了传统的依赖关系。众多的设计模式,比如插件,服务定位器或者依赖反转,则被用来在运行时把指定的低层组件实现提供给高层组件。
- 依赖倒置原则可以降低类间的耦合性。
- 依赖倒置原则可以提高系统的稳定性。
- 依赖倒置原则可以减少并行开发引起的风险。
- 依赖倒置原则可以提高代码的可读性和可维护性。
参考链接
[1]https://zh.wikipedia.org/wiki/%E4%BE%9D%E8%B5%96%E5%8F%8D%E8%BD%AC%E5%8E%9F%E5%88%99
[2]https://zhuanlan.zhihu.com/p/24175489
[3]http://c.biancheng.net/view/1326.html
[4]https://blog.csdn.net/king123456man/article/details/81626127