敏捷软件开发:原则、模式与实践——第11章 DIP:依赖倒置原则
第11章 DIP:依赖倒置原则
DIP:依赖倒置原则:
a.高层模块不应该依赖于低层模块。二者都应该依赖于抽象。
b.抽象不应该依赖于细节。细节应该依赖于抽象。
11.1 层次化
下图展示了一个简单的层次化方案:

高层的Policy层使用了低层的Mechanism层,而Mechanism层又使用了更细节的Utility层。它存在一个隐伏的错误特征,那就是:Policy层对于其下一直到Utility层的改动都是敏感的。依赖关系是传递的。
下图展示了一个更为合适的模型:

每个较高层次都为它所需要的服务声明一个抽象接口。较低层次实现了这些接口。每个高层类都通过该接口使用下一层。这样高层就不依赖于低层。低层反而依赖于高层中声明的抽象服务接口。
11.1.1 倒置的接口所有权
这里的倒置不仅仅是依赖关系的倒置,它也是接口所有权的倒置。我们通常会认为工具库应该拥有它们自己的接口。但是当应用了DIP时,我们发现往往是客户拥有抽象接口,而它们的服务则从这些接口派生。
这就是著名的Hollywood原则:“Don't call us, we'll call you.(不要调用我们,我们会调用你。)” 低层模块实现了在高层模块中声明并被高层模块调用的接口。
这里所说的所有权仅仅是指接口是随拥有它们的客户程序发布的,而非实现它们的服务器程序。接口和客户程序位于同一个包或者库中。这就迫使服务器程序库或者包依赖于客户程序库或者包。
当然,有时我们会不想让服务器程序依赖于客户程序,特别是当有多分客户程序但是服务器却仅有一份时。在这种情况下,客户程序必须得遵循服务接口,并把它发布到一个独立的包中。
11.1.2 依赖于抽象
程序中所有的依赖关系都应该终止于抽象类或者接口。
- 任何变量都不应该持有一个指向具体类的引用。
- 任何类都不应该从具体类派生。
- 任何方法都不应该重写它的任何基类中已经实现了的方法。
当然,每个程序都会有违反该启发规则的情况。有时必须创建具体类的实例,而创建这些实例的模块将会依赖于它们。此外,该启发规则对于那些虽然是具体但却稳定的来来说似乎不大合理。如果一个具体类不太会改变,并且也不会创建其他类似的派生类,那么依赖于它并不会造成损害。
比如,在大多数系统中,描述字符串的类都是具体的。例如,在C#中的String。该类是稳定的。也就是说,它不太会改变。因此,直接依赖于它不会造成伤害。
如果一个不稳定的类的接口必须变化是,这个变化一定会影响到表示该类的抽象接口。这种变化破坏了由抽象接口维系的隔离性。
可见,该启发规则对问题的考虑有点儿简单了。另一方面,如果看得更远一点,认为是客户模块或者层来声明它们需要的服务接口,那么仅当客户需要时才会对接口进行改变。这样,改变实现抽象接口的类就不会影响到客户。
结论
使用传统的过程化程序设计所创建出来的依赖关系结构、策略是依赖于细节的。这是糟糕的,因为这样会使策略受到细节的改变的影响。面向对象的程序设计倒置了依赖关系结构,使得细节和策略都依赖于抽象,并且常常是客户程序拥有服务接口。
事实上,这种依赖关系倒置正是好的面向对象设计的标志所在。使用何种语言编程是无关紧要的。如程序的依赖关系是倒置的,它就是面向对象的设计。如果程序的依赖关系不是倒置的,它就是过程化的设计。
摘自:《敏捷软件开发:原则、模式与实践(C#版)》Robert C.Martin Micah Martin 著
转载请注明出处:
作者:JesseLZJ
出处:http://jesselzj.cnblogs.com
敏捷软件开发:原则、模式与实践——第11章 DIP:依赖倒置原则的更多相关文章
- 六大设计原则(三)DIP依赖倒置原则
依赖倒置原则DIP(Dependence Inversion Principle) 依赖倒置原则的含义 高层模块不能依赖低层模块,二者都应该依赖其抽象. 抽象不应该依赖于细节. 细节应该依赖抽象. 什 ...
- DIP依赖倒置原则
一.定义 1.高层模块不应该依赖低层模块,二者都应该依赖抽象 2.抽象不应该依赖于细节.细节应该依赖于抽象 二.层次化 1.简单介绍 结构良好的面向对象架构都具有清晰的层次定义,每个层次通过一个定义良 ...
- 九 DIP 依赖倒置原则
首先看定义: 1.高层模块不依赖于低层模块,两者都应该依赖于抽象层 2.抽象不能依赖于细节,细节必须依赖于抽象 首先,模块是个抽象的概念,可以大到一个系统中的子系统作为一个模块,也可以是某个子系统中的 ...
- 【Scrum】-NO.40.EBook.1.Scrum.1.001-【敏捷软件开发:原则、模式与实践】- Scrum
1.0.0 Summary Tittle:[Scrum]-NO.40.EBook.1.Scrum.1.001-[敏捷软件开发:原则.模式与实践]- Scrum Style:DesignPattern ...
- 《敏捷软件开发-原则、方法与实践》-Robert C. Martin读书笔记(转)
Review of Agile Software Development: Principles, Patterns, and Practices 本书主要包含4部分内容,这些内容对于今天的软件工程师 ...
- 敏捷软件开发_实例2<四>
敏捷软件开发_实例2 上一章中对薪水支付案例的用例和类做了详细的阐述,在本篇会介绍薪水支付案例包的划分和数据库,UI的设计. 包的划分 一个错误包的划分 为什么这个包是错误的: 如果对classifi ...
- [设计模式]<<设计模式之禅>>关于依赖倒置原则
依赖倒置原则(Dependence Inversion Principle,DIP)这个名字看着有点别扭,“依赖”还“倒置”,这到底是什么意思?依赖倒置原则的原始定义是 High level modu ...
- ZT 3.1 依赖倒置原则的定义
设计模式精解-GoF 23 种设计模式解析附 C++实现源码http://www.mscenter.edu.cn/blog/k_eckelP58 Template 模式获得一种反向控制结构效果,这也是 ...
- 依赖倒置原则(Dependency Inversion Principle)
很多软件工程师都多少在处理 "Bad Design"时有一些痛苦的经历.如果发现这些 "Bad Design" 的始作俑者就是我们自己时,那感觉就更糟糕了.那么 ...
随机推荐
- Druid.io系列(二):基本概念与架构
原文链接: https://blog.csdn.net/njpjsoftdev/article/details/52955788 在介绍Druid架构之前,我们先结合有关OLAP的基本原理来理解Dr ...
- nginx转发请求
location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_add ...
- springMVC 踩过的坑 - 记录
1. 后台持久层Spring Jpa(即hibernate), 前台angularJS(angularJS只接受json串), 在后台使用DTO层对象代替domain(entity)与前台交互时, 传 ...
- 第一个 Windows 界面程序
编译器 使用的编译器为 Visual Studio 2017 菜单栏 -> 文件 -> 新建 -> 项目 选择 Windows 桌面应用程序,然后填好相关信息后点击“确定” 在解决方 ...
- 深入浅出 Java Concurrency (15): 锁机制 part 10 锁的一些其它问题
主要谈谈锁的性能以及其它一些理论知识,内容主要的出处是<Java Concurrency in Practice>,结合自己的理解和实际应用对锁机制进行一个小小的总结. 首先需要强调的 ...
- sysbench基准测试(2)——oltp.lua测试
前面知道sysbench基准测试的主要步骤为:prepare(准备数据集)→ run(运行测试)→ cleanup(清除数据集) 这一节介绍oltp.lua测试. oltp基准测试模拟了一个简单的事物 ...
- Program Size: data=9.0 xdata=0 code=47
data=47.0 编译器编译后,程序总共需要占用47字节的片内RAM空间.注意这个大小仅仅是累加而已,并未考虑各个块之间的空隙,也就是说实际占用的RAM空间可能多于此数值.xdata=0 程序未使用 ...
- nginx-rtmp-module--------------WIKI
https://github.com/arut/nginx-rtmp-module/wiki/Directives#idle_streams ============================= ...
- C++Primer笔记-----day04
1.函数指针.函数指针指向某种特定类型,函数的类型由它的返回类型和形参类型决定,与函数名无关.比如:bool lengthCompare(const string &,const string ...
- java反射(Field的应用)
//$Id: DirectPropertyAccessor.java 11405 2007-04-15 12:50:34Z max.andersen@jboss.com $ package org.h ...