1.定义:

高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

2.使用场景:

类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。即将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

3.使用特点

依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。
在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。
在实现依赖倒转原则时,我们需要针对抽象层编程,而将具体类的对象通过依赖注入(DependencyInjection, DI)的方式注入到其他对象中,依赖注入是指当一个对象要与其他对象发生依赖关系时,通过抽象来注入所依赖的对象。常用的注入方式有三种,分别是:构造注入,设值注入(Setter注入)和接口注入。构造注入是指通过构造函数来传入具体类的对象,设值注入是指通过Setter方法来传入具体类的对象,而接口注入是指通过在接口中声明的业务方法来传入具体类的对象。这些方法在定义时使用的是抽象类型,在运行时再传入具体类型的对象,由子类对象来覆盖父类对象。

4.实现案例

依赖倒置原则的核心思想是面向接口编程,我们依旧用一个例子来说明面向接口编程比相对于面向实现编程好在什么地方。场景是这样的:闲着无聊看书。代码如下:
class Book{public String getContent(){return "书中的故事";}
}
class Mother{public void narrate(Book book){System.out.println("闲着无聊");System.out.println(book.getContent());}
}
public class Client{public static void main(String[] args){Mother mother = new Mother();mother.narrate(new Book());}
}

运行结果:
闲着无聊
书中的故事
运行良好,假如有一天,需求变成这样:不是给书而是给一份报纸,报纸的代码如下:
class Newspaper{public String getContent(){return "报纸上的新闻";}
}

  这时候竟然不能读报纸! 只是将书换成报纸,居然必须要修改Mother才能读。假如以后需求换成杂志呢?换成网页呢?还要不断地修改Mother,这显然不是好的设计。原因就是Mother与Book之间的耦合性太高了,必须降低他们之间的耦合度才行。

我们引入一个抽象的接口IReader。读物,只要是带字的都属于读物:
interface IReader{public String getContent();
}

Mother类与接口IReader发生依赖关系,而Book和Newspaper都属于读物的范畴,他们各自都去实现IReader接口,这样就符合依赖倒置原则了,代码修改为:
class Newspaper implements IReader {public String getContent(){return "报纸上的新闻";}
}
class Book implements IReader{public String getContent(){return "书中的故事";}
}
class Mother{public void narrate(IReader reader){System.out.println("闲着无聊");System.out.println(reader.getContent());}
}
public class Client{public static void main(String[] args){Mother mother = new Mother();mother.narrate(new Book());mother.narrate(new Newspaper());}
}

运行结果:

闲着无聊
书中的故事
闲着无聊
报纸上的新闻
这样修改后,无论以后怎样扩展Client类,都不需要再修改Mother类了。这只是一个简单的例子,实际情况中,代表高层模块的Mother类将负责完成主要的业务逻辑,一旦需要对它进行修改,引入错误的风险极大。所以遵循依赖倒置原则可以降低类之间的耦合性,提高系统的稳定性,降低修改程序造成的风险。
采用依赖倒置原则给多人并行开发带来了极大的便利,比如上例中,原本Mother类与Book类直接耦合时,Mother类必须等Book类编码完成后才可以进行编码,因为Mother类依赖于Book类。修改后的程序则可以同时开工,互不影响,因为Mother与Book类一点关系也没有。参与协作开发的人越多、项目越庞大,采用依赖导致原则的意义就越重大。现在很流行的TDD开发模式就是依赖倒置原则最成功的应用。

5.注意事项

传递依赖关系有三种方式,以上的例子中使用的方法是接口传递,另外还有两种传递方式:构造方法传递和setter方法传递,相信用过Spring框架的,对依赖的传递方式一定不会陌生。
在实际编程中,我们一般需要做到如下3点:
(1)低层模块尽量都要有抽象类或接口,或者两者都有。
(2)变量的声明类型尽量是抽象类或接口。
(3)使用继承时遵循里氏替换原则。
依赖倒置原则的核心就是要我们面向接口编程,理解了面向接口编程,也就理解了依赖倒置。

转载于:https://www.cnblogs.com/yysbolg/p/7426479.html

设计模式原则(3)--Dependency Inversion Principle(DIP)--依赖倒转原则相关推荐

  1. 依赖倒转原则(Dependency Inversion Principle,DIP)

    前面两篇图文介绍了"开闭原则"和"里氏替换原则".开发出对扩展开放,对修改封闭的系统是程序员的目标,而今天所介绍的"依赖倒转原则"正是实现这 ...

  2. 依赖反转(倒置)原则(Dependency inversion principle,DIP)

    在软件设计.编码过程中有几个基本原则即SOLID原则,学习理解能够帮忙我们写出更健壮的代码.SOLID是五个基本原则的首字母.这五个原则如下: Single responsibility Open–c ...

  3. Java设计模式——依赖倒转原则

    一.什么是依赖倒转原则? 依赖倒转原则讲的是,要依赖于抽象,不要依赖于具体. 实现"开-闭"原则的关键是抽象化,并且从抽象化导出具体化实现."开-闭"原则是面向 ...

  4. 面向对象编程原则(06)——依赖倒转原则

    版权声明 本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl 参考资料 <大话设计模式> 作者:程杰 <Java设计模式> 作者:刘 ...

  5. java依赖倒转原则_设计原则之--依赖倒转原则

    [各位博友晚上好,又到了晚上的这个时间,感谢大家一直对Darren博客的支持,希望这篇文章对你有所帮助: 这几天一直在看设计模式:简单工厂模式,策略模式,单一职责原则,开放 [依赖倒转原则又称依赖倒置 ...

  6. 胖虎白话学习设计模式之依赖倒置原则(Dependence Inversion Principle)

    胖虎白话学习设计模式之依赖倒置原则(Dependence Inversion Principle) 记录胖虎学习设计模式过程,不许勿喷,转载请注明出处! (此博文为胖虎在PDF上截取.觉得写得通俗易懂 ...

  7. 【设计模式】依赖倒转原则(Dependence Inversion Principle)

    高层模块不应该依赖低层模块,两者都应该依赖其抽象:抽象不应该依赖细节,细节应该依赖抽象.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合. 1 案例分析(组装电脑 ...

  8. 依赖倒转原则 (Dependence Inversion Principle)

    依赖倒转原则 (Dependence Inversion Principle) 定义:程序要依赖于抽象接口,不要依赖于具体实现.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实 ...

  9. 深入理解依赖倒置原则(Dependence Inversion Principle)

    Dependence Inversion Principle 依赖倒置原则(Dependence Inversion Principle) What 什么是依赖倒置原则? Why 为什么使用依赖倒置原 ...

最新文章

  1. SDWebImage 在Swift中遇坑解决
  2. Cookie,Session的区别
  3. Python操纵Mysql数据库的三种方法,实现增删改查
  4. github page hexo博客gitee_hexo + github 博客搭建
  5. JVM总结---各处总结
  6. 对“粘连”footer布局的思考和总结
  7. Java Socket编程详解
  8. 【JS 逆向百例】无限 debugger 绕过,某网站互动数据逆向
  9. 图解 CSS (1): 先做一个样式表测试工具
  10. C++:基于范围的for循环
  11. android 电池小记
  12. DHCP中继原理和配置(含常见配置配置误区)
  13. Centos7.9源码编译安装Apache
  14. yaws mysql_MySQL入门之C语言操作MySQL
  15. Qt样式表Qss(什么是QSS;基本语法;setStyleSheet函数;样式表的属性值;利用QtCreate实现样式切换;样式表实现皮肤改变实例)
  16. Xshell6下载安装
  17. java实现令牌桶算法
  18. Excel自动获取单词音标词义
  19. 急需“五彩连珠”小游戏的代码
  20. 流媒体相关资源下载地址(整理)

热门文章

  1. 深度学习《CycleGAN》
  2. tensorflow中用saver保存模型
  3. Python语法入门
  4. 改善深层神经网络:超参数调整、正则化以及优化——2.2 理解Mini-batch梯度下降法
  5. leetcode - 1201. 丑数 III
  6. 易理解的海明码的编码和校验原理【转载】
  7. VC 位图按钮CBitmapButton的使用
  8. GOF之行为型模式Ⅰ(重点)
  9. python爬虫requests源码链家_python爬虫——爬取链家房价信息(未完待续)
  10. java axure_【Java】Axure线框图