文章目录

  • 依赖反转原则(DIP)
    • 正确理解
      • 优势
  • 控制反转
    • 例子
  • 依赖注入(DI)
    • 例子
    • 依赖注入框架
    • 对比基于接口编程
      • 相同点
      • 区别
      • 总结

依赖反转原则(DIP)

  • 高层模块(high-level modules)不要依赖低层模块(low-level)。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。除此之外,抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions)。
  • 在调用链上,调用者属于高层,被调用者属于低层。在平时的业务代码开发中,高层模块依赖底层模块是没有任何问题的。实际上,这条原则主要还是用来指导框架层面的设计,

正确理解

  • 依赖倒置原则概念是高层次模块不依赖于低层次模块。看似在要求高层次模块,实际上是在规范低层次模块的设计。低层次模块提供的接口要足够的抽象、通用,在设计时需要考虑高层次模块的使用种类和场景。
  • 明明是高层次模块要使用低层次模块,对低层次模块有依赖性。现在反而低层次模块需要根据高层次模块来设计,出现了「倒置」的显现
  • 把原本的高层建筑依赖底层建筑“倒置”过来,变成底层建筑依赖高层建筑。高层建筑决定需要什么,底层去实现这样的需求,但是高层并不用管底层是怎么实现的。这样就不会出现前面的“牵一发动全身”的情况。
  • 控制反转(Inversion of Control) 就是依赖倒置原则的一种代码设计的思路。具体采用的方法就是所谓的依赖注入(Dependency Injection)。

优势

  1. 低层次模块更加通用,适用性更广,能更好的适应业务需求的变化
  2. 高层次模块没有依赖低层次模块的具体实现,方便低层次模块的替换

控制反转

  • "控制反转"控制反转的英文翻译是 Inversion Of Control,缩写为 IOC。
  • 框架提供了一个可扩展的代码骨架,用来组装对象、管理整个执行流程。程序员利用框架进行开发的时候,只需要往预留的扩展点上,添加跟自己业务相关的代码,就可以利用框架来驱动整个程序流程的执行。
  • 这里的“控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程可以通过框架来控制。流程的控制权从程序员“反转”到了框架。
  • 实现控制反转的方法有很多,除了类似于模板设计模式的方法之外,还有依赖注入等方法,所以,控制反转并不是一种具体的实现技巧,而是一个比较笼统的设计思想,一般用来指导框架层面的设计

例子


public abstract class TestCase {public void run() {if (doTest()) {System.out.println("Test succeed.");} else {System.out.println("Test failed.");}}public abstract boolean doTest();
}public class JunitApplication {private static final List<TestCase> testCases = new ArrayList<>();public static void register(TestCase testCase) {testCases.add(testCase);}public static final void main(String[] args) {for (TestCase case: testCases) {case.run();}}
  • 我们只需要在框架预留的扩展点,也就是 TestCase 类中的 doTest() 抽象函数中,填充具体的测试代码就可以实现之前的功能了,完全不需要写负责执行流程的 main() 函数了
  • 这个例子,就是典型的通过框架来实现“控制反转”的例子。框架提供了一个可扩展的代码骨架,用来组装对象、管理整个执行流程。程序员利用框架进行开发的时候,只需要往预留的扩展点上,添加跟自己业务相关的代码,就可以利用框架来驱动整个程序流程的执行。

依赖注入(DI)

  • 依赖注入跟控制反转恰恰相反,它是一种具体的编码技巧。依赖注入的英文翻译是 Dependency Injection,缩写为 DI
    • 不通过 new() 的方式在类内部创建依赖类对象,而是将依赖的类对象在外部创建好之后,通过构造函数、函数参数等方式传递(或注入)给类使用
  • 通过依赖注入的方式来将依赖的类对象传递进来,这样就提高了代码的扩展性,我们可以灵活地替换依赖的类,其实就是开闭原则
  • 这个概念,有一个非常形象的说法,那就是:依赖注入是一个标价 25 美元,实际上只值 5 美分的概念。也就是说,这个概念听起来很“高大上”,实际上,理解、应用起来非常简单。
  • 它是编写可测试性代码最有效的手段。

例子


// 非依赖注入实现方式
public class Notification {private MessageSender messageSender;public Notification() {this.messageSender = new MessageSender(); //此处有点像hardcode}public void sendMessage(String cellphone, String message) {//...省略校验逻辑等...this.messageSender.send(cellphone, message);}
}public class MessageSender {public void send(String cellphone, String message) {//....}
}
// 使用Notification
Notification notification = new Notification();// 依赖注入的实现方式
public class Notification {private MessageSender messageSender;// 通过构造函数将messageSender传递进来public Notification(MessageSender messageSender) {this.messageSender = messageSender;}public void sendMessage(String cellphone, String message) {//...省略校验逻辑等...this.messageSender.send(cellphone, message);}
}
//使用Notification
MessageSender messageSender = new MessageSender();
Notification notification = new Notification(messageSender);

依赖注入框架

  • 在实际的软件开发中,一些项目可能会涉及几十、上百、甚至几百个类,类对象的创建和依赖注入会变得非常复杂
  • 如果这部分工作都是靠程序员自己写代码来完成,容易出错且开发成本也比较高。
  • 而对象创建和依赖注入的工作,本身跟具体的业务无关,我们完全可以抽象成框架来自动完成。
  • 现成的依赖注入框架有很多,比如 Google Guice、Java Spring、Pico Container、Butterfly Container 等

对比基于接口编程

  • 但是通常情况下依赖注入加上基于接口威力更大,接口把依赖抽象化,传入不同对接口的实现可以很好实现对扩展开放的原则,也就是说它们可以相辅相成

相同点

  • "基于接口而非实现编程"与"依赖注入"的联系是二者都是从外部传入依赖对象而不是在内部去new一个出来

区别

  • 区别是"基于接口而非实现编程"强调的是"接口",强调依赖的对象是接口,而不是具体的实现类,而"依赖注入"不强调这个,类或接口都可以,只要是从外部传入不是在内部new出来都可以称为依赖注入。
  • 依赖注入是一种具体编程技巧,关注的是对象创建和类之间关系,目的提高了代码的扩展性,我们可以灵活地替换依赖的类。.基于接口而非实现编程是一种设计原则,关注抽象和实现,上下游调用稳定性,目的是降低耦合性,提高扩展性。

总结

  • 基于接口而非实现编程,是一种指导编码的思想。依赖注入是它的一种具体应用

设计原则—SOLID(DIP)相关推荐

  1. 六大设计原则SOLID

    六大设计原则SOLID 一.SOLID 设计模式的六大原则 二.单一职责原则 (Single Responsibility Principle) 1. 单一职责原则定义 2. 问题由来 3. 解决方案 ...

  2. 【六大设计原则-SOLID】

    SOLID简介: 历史:由Robert C·Martin汇总并推广 目标: 使软件更容易被改动 是软件更容易被理解 构建可以在多个软件系统中复用的组件 组成: 名称 简写 含义 单一职责原则 SRP ...

  3. 设计原则——SOLID

    SOLID是5个设计原则的统称,它们分别是:单一职责原则.开闭原则.里式替换原则.接口隔离原则和依赖反转原则,依次对应SOLID中的S.O.L.I.D. 1.单一职责原则 单一职责原则,Single ...

  4. 六大设计原则(SOLID)

    一.SOLID 设计模式的六大原则有: Single Responsibility Principle:单一职责原则 Open Closed Principle:开闭原则 Liskov Substit ...

  5. 流行20年的架构设计原则SOLID可能已经不适合微服务了

    点击上方"服务端思维",选择"设为星标" 回复"669"获取独家整理的精选资料集 回复"加群"加入全国服务端高端社群「后 ...

  6. 六大设计原则 (SOLID)

    设计原则概述 设计模式中主要有六大设计原则,简称为SOLID ,是由于各个原则的首字母简称合并的来(两个L算一个,solid 稳定的),六大设计原则分别如下: 1.单一职责原则(Single Resp ...

  7. 软件设计原则SOLID+组合聚合+迪米特原则(附代码讲解)

    SOLID是五大设计原则的首字母简写,最早出现于出自Robert Martin(罗伯特. 马丁)的<架构整洁之道>第三章设计原则.他们分别是 single Responsibility P ...

  8. 设计原则—SOLID(LSP)

    文章目录 里氏替换原则 落地 测试 反例 子类违背父类声明要实现的功能 子类违背父类对输入.输出.异常的约定 异常 输入 子类违背父类注释中所罗列的任何特殊说明 意义 对比多态 改进已有实现 指导程序 ...

  9. 设计原则—SOLID(SRP)

    文章目录 SOLID 单一职责原则 其他判断标准 过于单一的拆分 例子 序列化 例子 用户信息的例子 从实际场景的角度出发 从业务的角度出发 总结 SOLID 单一职责原则.开闭原则.里式替换原则.接 ...

最新文章

  1. scrapy 6023 telnet查看爬虫引擎相关状态
  2. python编程做什么工作-Python能做什么工作?
  3. 跨进程信息交互真个费事。
  4. div 上禁止复制的css实现方法
  5. 清空mysql注册表步骤_完全卸载MySQL 数据库清空MySql注册表
  6. Scala教程之:Enumeration
  7. 常用web服务列表(三)
  8. 360技术嘉年华第七季——测试之美 报名啦
  9. PAT甲级1017 (模拟排序)
  10. C# 5.0将带来的五大新特性
  11. python课堂随机点名_【工作中的Python】随机点名小脚本
  12. 【渝粤教育】广东开放大学 建筑专业 形成性考核 (57)
  13. linux调度器(六)——应用层理解CFS及组调度
  14. 财务常用软件哪个好用?
  15. ESP_Easy BME280 WIFI MQTT传感器制作
  16. Rational Rose 2016
  17. Deepin常用命令、系统命令、Vi命令
  18. 登录页面(含后台)login.php
  19. Python之私有属性和私有方法
  20. 解析SCUT FIR Pedestrian Dataset数据

热门文章

  1. proxy代理服务器的使用
  2. SHA512系列哈希算法原理及实现(附源码)
  3. 数据库面试题:Mysql如何进行死锁检测
  4. Spring与Mybatis整合
  5. python箱线图异常值_Python数据清洗--异常值识别与处理01
  6. 0x7FFFFFFF+0x7FFFFFFF 是多少
  7. POJ2502 Subway 最短路
  8. B/S架构(浏览器和服务器架构模式)
  9. PTA---6-1 atof函数的实现 (10分)
  10. 数学函数 php,php数学函数