依赖倒转原则(Dependency Inversion Principle)是面向对象设计中的另一个基本原则,它是由Robert C. Martin提出的,它的中心思想是面向接口编程,该原则指出高层模块不应该依赖于低层模块,两者都应该依赖于抽象;抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。原因是相比于细节的多变性,抽象要稳定的多,因此以抽象作为基础搭建的框架,要比以细节作为基础搭建的框架稳定的多,而java中的抽象是指抽象类和接口,细节是指具体的实现,因此抽象类和接口的价值在于设计,而不涉及具体的操作,具体的操作交给实现类完成。
举例:
模拟实现支付功能,在日常生活中,支付方式有很多种,微信支付,现金支付,支付宝支付等等,实现过程如下所示:
package Reaplcetest; public class DependecyInversion1 { public static void main(String[] args) { Person person = new Person(); person.Paying(new Cash()); person.Paying(new WeChat()); person.Paying(new Alipay()); } } //将抽象方法分别写在了具体的实现类中 //现金支付 class Cash{ public String getInfo() { return "欢迎使用现金支付"; } } //微信支付 class WeChat{ public String getInfo(){ return "欢迎使用微信支付"; } } //支付宝支付 class Alipay{ public String getInfo(){ return "欢迎使用支付宝支付"; } } class Person{ //支付方式为抽象的概念,它依赖具体的实现类去实现---不符合依赖倒转原则 public void Paying(Cash cash) { System.out.println(cash.getInfo()); } public void Paying(WeChat weChat) { System.out.println(weChat.getInfo()); } public void Paying(Alipay alipay) { System.out.println(alipay.getInfo()); } }
上述这种实现方式就不满足依赖倒转原则中的抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象,具体表现为:支付方式本身就是一个抽象的,不具体的概念,它的具体实现我们是不确定的,而上述这种实现是把支付方式依赖于cash,WeChat,Alipay这三个实现类
那么我们如何进行改进呢?解决思路:引入一个抽象的接口Pay,表示支付方式,因为无论是cash,WeChat还是Alipay等等都属于支付方式的范畴,它们各自实现IPay接口就可以了,这样就符合了依赖
倒转原则
package Reaplcetest; public class DependecyInversion1Improve { public static void main(String[] args) { Person person = new Person(); person.Paying(new Cash()); person.Paying(new WeChat()); person.Paying(new Alipay()); } } //表示支付方式的接口 interface Pay{ //表示支付方式的抽象方法 public String getInfo(); } //具体的实现支付的类 //现金支付 class Cash implements Pay{ @Override public String getInfo() { return "欢迎使用现金支付"; } } //微信支付 class WeChat implements Pay{ @Override public String getInfo() { return "欢迎使用微信支付"; } } //支付宝支付 class Alipay implements Pay{ @Override public String getInfo() { return "欢迎使用支付宝支付"; } } class Person{ //支付方式不需要依赖具体的实现类才能实现,而是通过创建它的接口对象即可 public void Paying(Pay pay) { System.out.println(pay.getInfo()); } }
其实依赖倒转原则要求我们通过抽象来实现模块间的解耦,具体的实现细节应该依赖于抽象,反过来则不是。这样可以提高代码的可维护性、可扩展性和可测试性。
什么是底层模块?什么是高层模块?
低层模块是指实现系统中基本功能的模块,它们通常负责与硬件或底层操作系统交互,提供底层的功能和服务,通常是对系统资源的直接访问,例如驱动程序、操作系统接口、底层算法等。
高层模块是指在低层模块基础上构建的更高级别的模块,它们通常负责实现系统的业务逻辑和功能组合。高层模块通常是对低层模块的封装和组织,提供更高级别的抽象和接口,使系统更易于理解和使用。通常是用户界面、业务逻辑、数据处理等。
低层模块和高层模块的划分是为了提高软件系统的可维护性和可扩展性。低层模块负责底层的具体实现,可以提供给高层模块使用,而高层模块则可以更加关注系统的业务逻辑和功能实现,不需要关心底层的具体实现细节。这种分层的设计可以提高代码的可重用性和可维护性,也方便对系统进行扩展和修改。