敏捷软件开发:原则、模式与实践——第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" 的始作俑者就是我们自己时,那感觉就更糟糕了.那么 ...
随机推荐
- 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...
- Tkinter Message
Python GUI - Tkinter Message(消息):这个小工具提供了一个多和不可编辑的对象,显示文本,自动断行和其内容的理由. 这个小工具提供了一个多和不可编辑的对象,显示文本,自动 ...
- 07_java之练习题
01奇数求和练习 * A: 奇数求和练习 * a: 题目分析 * 为了记录累加和的值,我们需要定义一个存储累加和的变量 * 我们要获取到1-100范围内的数 * 判断当前数是否为奇数,是奇数,完成累加 ...
- URL里面的中文参数到底转换成了什么?
https://www.amazon.cn/s/ref=nb_sb_noss?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99& ...
- 「小程序JAVA实战」小程序多媒体组件(27)
转自:https://idig8.com/2018/08/19/xiaochengxujavashizhanxiaochengxuduomeitizujian27/ 来说下 ,小程序的多媒体组件.源码 ...
- 用Python将word文件转换成html(转)
用Python将word文件转换成html 序 最近公司一个客户大大购买了一堆医疗健康方面的科普文章,希望能放到我们正在开发的健康档案管理软件上.客户大大说,要智能推送!要掌握节奏!要深度学习!要 ...
- maven-resources-plugin使用
命令行中带参数指定${}变量值 <build> <resources> <resource> <directory>src/main/resources ...
- Django 实现用户认证set_Cookie
当用户通过认证时,set_Cookie(key, value) request.Cookie.get(key) 如果key不为空,就说明验证通过,否者重新跳转回login登录页面 对于URL urlp ...
- MySQL 复合索引
一. 1.索引越少越好,在修改数据时,第个索引都要进行更新,降低写速度.2.最窄的字段放在键的左边3.避免file sort排序,临时表和表扫描. 二.复合索引的建立原则: 如果您很可能仅对一个列多次 ...
- flutter photo_view的改造
app中对图片的浏览.缩放是一个常用的功能,目前有一款插件photo_view,基本上可以满足这些功能,但是有些地方需要修改完善 1.双击放大的时候,有三个状态,会有一个放大的中间状态,需要点击三次才 ...