设计原则之依赖倒转原则
依赖倒转原则(DIP): 高层模块不应该依赖低层模块,两者都应该依赖其抽象抽象不应该依赖细节,细节应该依赖抽象。
依赖倒置原则在Java语言中的表现:
模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的
接口或抽象类不依赖于实现类
实现类依赖于接口或抽象类
更为精简的定义: 面向接口编程(Object-Oriented Design, OOD)
DIP的好处: 采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
DIP的几种写法
接口声明依赖对象: 在接口的方法中声明依赖对象。
构造函数传递依赖对象: 在类中通过构造函数声明依赖对象(好比Spring中的构造器注入),采用构造器注入。
Setter方法传递依赖对象: 在抽象中设置Setter方法声明依赖对象(Spring中的方法注入)。
依赖倒置原则的本质: 就是通过抽象(抽象类或接口)使各个类或模块实现彼此独立,不互相影响,实现模块间的松耦合。
在项目中使用这个规则需要以下原则;
每个类尽量都要有接口或抽象类,或者抽象类和接口都有: 依赖倒置原则的基本要求,有抽象才能依赖倒置。
变量的表面类型尽量是接口或者抽象类。
任何类都不应该从具体类派生。
尽量不要重写基类已经写好的方法(里式替换原则)。
结合里式替换原则来使用: 结合里式替换原则和依赖倒置原则我们可以得出一个通俗的规则,接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化。
一句话:依赖倒置原则的核心就是面向抽象(抽象类或者接口)编程
案例1:
未遵守依赖倒转原则
组装电脑:
现要组装一台电脑,需要配件cpu,硬盘,内存条。只有这些配置都有了,计算机才能正常的运行。选择cpu有很多选择,如Intel,AMD等,硬盘可以选择希捷,西数等,内存条可以选择金士顿,海盗船等。
类图
希捷硬盘类
/*** 希捷硬盘*/
public class XiJieHardDisk {//存储数据的方法public void save(String data) {System.out.println("使用希捷硬盘存储数据为:" + data);}//获取数据的方法public String get() {System.out.println("使用希捷硬盘取数据");return "数据";}
}
金士顿内存条类
/*** 金士顿内存条类*/
public class KingstonMemory {public void save() {System.out.println("使用金士顿内存条");}
}
因特尔cup类
/*** Intel cpu*/
public class IntelCpu {public void run() {System.out.println("使用Intel处理器");}
}
电脑类
/*** Computer*/
public class Computer {private XiJieHardDisk hardDisk;private IntelCpu cpu;private KingstonMemory memory;public XiJieHardDisk getHardDisk() {return hardDisk;}public void setHardDisk(XiJieHardDisk hardDisk) {this.hardDisk = hardDisk;}public IntelCpu getCpu() {return cpu;}public void setCpu(IntelCpu cpu) {this.cpu = cpu;}public KingstonMemory getMemory() {return memory;}public void setMemory(KingstonMemory memory) {this.memory = memory;}public void run() {System.out.println("运行计算机");String data = hardDisk.get();System.out.println("从硬盘上获取的数据是:" + data);cpu.run();memory.save();}
}
测试类(测试组装的电脑)
/*** ComputerDemo*/
public class ComputerDemo {public static void main(String[] args) {//创建组件对象XiJieHardDisk hardDisk = new XiJieHardDisk();IntelCpu cpu = new IntelCpu();KingstonMemory memory = new KingstonMemory();//创建计算机对象Computer c = new Computer();//组装计算机c.setCpu(cpu);c.setHardDisk(hardDisk);c.setMemory(memory);//运行计算机c.run();}
}
测试结果
上面代码可以看到已经组装了一台电脑,但是似乎组装的电脑的cpu只能是Intel的,内存条只能是金士顿的,硬盘只能是希捷的,这对用户肯定是不友好的,用户有了机箱肯定是想按照自己的喜好,选择自己喜欢的配件。
案例2:
根据依赖倒转原则进行改进:
代码我们只需要修改Computer类,让Computer类依赖抽象(各个配件的接口),而不是依赖于各个组件具体的实现类。
类图
cpu接口
/*** @Description: cpu接口*/
public interface Cpu {//运行cpupublic void run();
}
硬盘接口
/*** @Description: 硬盘接口*/
public interface HardDisk {//存储数据public void save(String data);//获取数据public String get();
}
内存条接口
/*** @Description: 内存条接口*/
public interface Memory {public void save();
}
英特尔CPU类(实现CPU接口)
/*** @Description: Intel cpu*/
public class IntelCpu implements Cpu {public void run() {System.out.println("使用Intel处理器");}
}
希捷硬盘类(实现硬盘接口)
/*** 希捷硬盘*/
public class XiJieHardDisk implements HardDisk {//存储数据的方法public void save(String data) {System.out.println("使用希捷硬盘存储数据为:" + data);}//获取数据的方法public String get() {System.out.println("使用希捷希捷硬盘取数据");return "数据";}
}
金士顿内存条类(实现内存条接口)
/*** 金士顿内存条类*/
public class KingstonMemory implements Memory {public void save() {System.out.println("使用金士顿内存条");}
}
电脑类(依赖各个组件的接口)
/*** @ClassName: Computer*/
public class Computer {private HardDisk hardDisk;private Cpu cpu;private Memory memory;public HardDisk getHardDisk() {return hardDisk;}public void setHardDisk(HardDisk hardDisk) {this.hardDisk = hardDisk;}public Cpu getCpu() {return cpu;}public void setCpu(Cpu cpu) {this.cpu = cpu;}public Memory getMemory() {return memory;}public void setMemory(Memory memory) {this.memory = memory;}//运行计算机public void run() {System.out.println("运行计算机");String data = hardDisk.get();System.out.println("从硬盘上获取的数据是:" + data);cpu.run();memory.save();}
}
测试类
/*** 测试类*/
public class ComputerDemo {public static void main(String[] args) {//创建计算机的组件对象HardDisk hardDisk = new XiJieHardDisk();Cpu cpu = new IntelCpu();Memory memory = new KingstonMemory();//创建计算机对象Computer c = new Computer();//组装计算机c.setCpu(cpu);c.setHardDisk(hardDisk);c.setMemory(memory);//运行计算机c.run();}
}
解释说明:
面向对象的开发很好的解决了这个问题,一般情况下抽象的变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。
即使实现细节不断变动,只要抽象不变,客户程序就不需要变化。这大大降低了客户程序与实现细节的耦合度。
当组装别的品牌组件时,只需要实现对应的接口即可。
结束!!!!!!!
人们不愿意相信一个土匪的名字叫牧之
设计原则之依赖倒转原则相关推荐
- java依赖倒转原则_设计原则之--依赖倒转原则
[各位博友晚上好,又到了晚上的这个时间,感谢大家一直对Darren博客的支持,希望这篇文章对你有所帮助: 这几天一直在看设计模式:简单工厂模式,策略模式,单一职责原则,开放 [依赖倒转原则又称依赖倒置 ...
- 面向对象编程原则(06)——依赖倒转原则
版权声明 本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl 参考资料 <大话设计模式> 作者:程杰 <Java设计模式> 作者:刘 ...
- Java里氏转换_里氏代换原则、依赖倒转原则 | 学步园
里氏代换原则 面向对象设计的重要原则是创建抽象化,并且从抽象化导出具体化,具体化也就是给出不同的实现. 继承关系就是一种从抽象化到具体化的导出. 里氏代换原则:如果对每一个类型为T1的对象o1,都有类 ...
- 带你认识六种设计原则(开闭原则、里氏代换原则、依赖倒转原则....)
前言 1. 设计原则 1.1. 开-闭原则 1.2. 里氏代换原则 1.3. 依赖倒转原则 1.4. 接口隔离原则 1.5. 合成/聚合原则 1.6. 迪米特法则 前言 学习设计模式之前先要了解其中的 ...
- Java设计模式之设计的6大原则(开闭原则,里氏代换原则,依赖倒转原则,接口隔离原则,最少知道原则,合成复用原则)
1. 开闭原则 核心思想:一个对象对外扩展开发,对修改关闭 意思就是:对类的改动是通过增加代码进行的,而不是修改现有的代码. 也就是说软件开发人员一旦写出了可以运行的代码,就不应该去改动它,而是要保证 ...
- 三、单一职责原则、开放-封闭原则、依赖倒转原则
一.单一职责原则 1.定义:就一个类而言,应该仅有一个引起它变化的原因. 2.为什么要?:如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力 ...
- 设计模式 学习笔记(2)单一职责原则、开放封闭原则、依赖倒转原则
(3)单一职责原则 单一职责原则(SRP),就一个类而言,应该仅有一个引起它变化的原因.例如,我们在写一个窗体应用程序,一般都会生成一个Form这样的类,于是我们就把各种各样的代码,像算法.数据库访问 ...
- 设计模式——(四)设计模式原则___依赖倒转原则
一.介绍 依赖倒转原则是指: 1)高层模块不应该依赖低层模块,二者都应该依赖其抽象. 2)抽象不应该依赖细节,细节应该依赖抽象. 3)依赖倒转原则的中心思想是面向接口编程. 4)依赖倒转原则是基于这样 ...
- 【设计模式】七大原则之“依赖倒转原则”
一 基本介绍 依赖倒转原则(Dependence Inversion Principle)是指: 高层模块不应该依赖低层模块,二者都应该依赖其抽象 抽象不应该依赖细节,细节应该依赖抽象 依赖倒转(倒置 ...
最新文章
- javascript学习之基本概念
- android中怎么网络判断,Android中判断网络是否连接实例详解
- MyEclipse连接MySQL时遇到的各种烦人事
- java String format占位符
- 防止Stack smash的技术
- 《SAS编程与数据挖掘商业案例》学习笔记之三
- GoogleNet_V3结构(论文复现)
- matlab简单分析短时傅里叶变换STFT
- 谢谢你,阅读了这篇文章
- 剑指offer之二叉搜索树与双向链表
- B站还有多久成为天涯
- 搜狐老矣,尚能饭否?
- linux集群高可用--crm
- 如何将域名指向本地服务器
- Queen Collisions(分行列模拟)
- vue路由详解 --基础
- win10远程桌面连接计算机密码错误,访问win10的远程桌面(Remote Desktop)总是凭据或者用户密码错误...
- 什么是WAF?WAF的功能有哪些?
- Matlab plot绘图颜色详解
- 郎平,你回来会毁了中国女排!