目录

介绍

先决条件

依赖倒置原则(DIP)

总结


介绍

在处理WPF应用程序时,我遇到过诸如Unity容器,IoC,依赖注入之类的术语。当时,我很迷茫,想着这一切的需要。但后来,当我逐渐了解到它的好处时,我意识到它的实际需要。

在本文中,我将尝试解释DI和IoC的需求和用法。基本上,本文分为五个部分:

  • 第1部分:依赖反转原理(当前正在阅读)
  • 第2部分:控制反转和IoC容器
  • 第3部分:自定义IoC容器
  • 第4部分:具有生命周期选项的自定义IoC容器
  • 第5部分:使用Microsoft Unity的依赖项注入(DI)

本文的这一部分是关于依赖倒置原理的。希望您会发现本文易于理解和实现。

先决条件

最好对以下项一无所知:

  • 开闭原则
  • 接口隔离原理

依赖倒置原则(DIP)

DIP是SOLID原则之一,由Robert Martin C.先生在1992年提出。

  • S —— 单一责任原则
  • O—— 开/关原理
  • L —— Liskov替代原理
  • I ——接口隔离原理
  • D——依赖反转原理

根据罗伯特·马丁(C. Robert Martin)的依赖倒置原则:

  1. 高级模块不应依赖于低级模块。两者都应依赖抽象。
  2. 抽象不应依赖细节。细节应依赖于抽象。

DIP是指将常规依赖性从高级模块转换为低级模块。

Bob Martin Peper期刊的示例:

在图1中,一个复制程序(高级模块)从键盘读取并写入打印机。这里的复制程序取决于Read KeyboardWrite Printer并紧密耦合

public class Copy
{public void DoWork(){ReadKeyboard reader = new ReadKeyboard();WritePrinter writer = new WritePrinter();string data = reader.ReadFromKeyboard();writer.WriteToPrinter(data);}
}

在我们要求向程序中添加更多读取器或写入器之前,此实现似乎非常好。在这种情况下,我们需要更改复制程序以适应新的读者和作家,并且需要编写条件语句,该条件语句将根据用途选择读者和作家,这违反了面向对象设计的“打开/关闭”原理。

例如,我们要扩展复印程序(参见图1.b),该程序也可以从扫描仪读取并写入闪存盘。在这种情况下,我们需要修改复制程序:

public class Copy
{public void DoWork(){string data;switch (readerType){case  "keyboard":ReadKeyboard reader = new ReadKeyboard();data = reader.ReadFromKeyboard();break;case "scanner":ReadScanner reader2 = new ReadScanner();data = reader2.ReadFromScanner();break;}switch (writerType){case "printer":WritePrinter writer = new WritePrinter();writer.WriteToPrinter(data);break;case "flashdisk":WriteFlashDisk writer2 = new WriteFlashDisk();writer2.WriteToFlashDisk(data);break;}}
}

同样,如果您继续添加更多读取器或写入器,则我们需要更改复制程序的实现,因为复制程序取决于读取器和写入器的实现。

为了解决这个问题,我们可以修改copy程序,使其依赖于抽象而不是依赖于实现。下图说明了反转依赖关系。

在上图中,Copy程序依赖于两个抽象,IReader和IWriter来执行。只要底层组件能够对抽象进行确认,copy程序就可以从这些组件中读取内容。

例如,在上图中,ReadKeyboard实现IReader接口和WritePrinter实现IWriter,因此使用IReader和IWriter接口复制程序可以执行复制操作。因此,如果我们需要添加更多低级组件(如扫描仪和闪存盘),则可以通过从扫描仪和闪存盘来实现。以下代码说明了这种情况:

public interface IReader
{string Read();
}public interface IWriter
{void Write(string data);
}public class ReadKeyboard : IReader
{public string Read(){// code to read from keyboard and return as string}
}public class ReadScanner : IReader
{public string Read(){// code to read from scanner and return as string}
}public class WritePrinter : IWriter
{public void Write(string data){// code to write to the printer}
}public class WriteFlashDisk : IWriter
{public void Write(string data){// code to write to the flash disk}
}public class Copy
{private string _readerType;private string _writerType;public Copy(string readerType, string writerType){_readerType = readerType;_writerType = writerType;}public void DoWork(){IReader reader;IWriter writer;string data;switch (readerType){case  "keyboard":reader = new ReadKeyboard();break;case "scanner":reader = new ReadScanner();break;}switch (writerType){case "printer":writer = new WritePrinter();break;case "flashdisk":writer = new WriteFlashDisk();break;}data = reader.Read();writer.Write(data);}
}

在这种情况下,细节依赖于抽象,但高级类仍依赖于低级模块。在实例化高级模块范围内的低级模块对象时,高级模块仍然需要在添加新的低级组件时进行修改,这不能完全满足DIP。

为了删除依赖关系,我们需要在高级模块之外创建依赖关系对象(低级组件),并且应该有某种机制将该依赖关系对象传递给依赖模块。

现在出现了一个新问题,即如何实现依赖倒置。

上述问题的答案之一可以是控制反转(IoC)。考虑以下代码段:

public class Copy
{public void DoWork(){IReader reader = serviceLocator.GetReader();IWriter writer = serviceLocator.GetWriter();string data = reader.Read();writer.Write(data);}
}

高亮显示的代码替换了实例化读取器和写入器对象的逻辑。在这里,我们将控件创建从Copy程序(高级模块)转换为服务定位器。因此,copy无需通过添加/删除低级模块来更改程序。

依赖注入是实现IoC的机制之一。在本文的下一部分中,我将介绍什么是控制反转(IoC),以及使用不同机制(依赖注入(DI)是实现之一)实现依赖反转原理的方法。

总结

在本文的这一部分中,我已经解释了依赖性反转原理(DIP)及其在实时场景中的需求。

在本文的后面,我将解释控制反转(IoC)和依赖注入(DI)。

依赖反转原理,IoC容器和依赖注入:第1部分相关推荐

  1. 依赖反转原理,IoC容器和依赖注入:第5部分

    目录 介绍 总览 依赖注册 实例注册 工厂注册 类型注册 样例应用程序 总结 介绍 这是我关于依赖反转原理和依赖注入的文章的第五部分也是最后一部分.在上一部分中,我实现了一个自定义容器,其功能非常有限 ...

  2. 依赖反转原理,IoC容器和依赖注入:第4部分

    目录 介绍 背景 LifeTimeOption的实现 总结 下载源代码18.5 KB 介绍 这是我有关依赖反转原理,IoC容器和依赖注入的文章的第四部分.在本文的上半部分,我试图解释如何构建自己的Io ...

  3. 依赖反转原理,IoC容器和依赖注入:第3部分

    目录 介绍 背景 自定义IoC容器的工作方式 自定义IoC容器 高级模块的使用者 编码自定义IoC容器 步骤1:在Visual Studio中创建一个空白解决方案,并创建以下项目 步骤2:将以下代码添 ...

  4. 依赖反转原理,IoC容器和依赖注入:第2部分

    目录 介绍 控制反转(IoC) 什么是控制反转 接口反转 流反转 创建反转 依赖注入 总结 介绍 这是有关依赖反转原理,IoC容器和依赖注入的文章的继续部分.在本文的上半部分,我解释了什么是依赖反转原 ...

  5. spring源码分析第三天------spring核心IOC容器和依赖注入原理

    基于XML的依赖注入 1.依赖注入发生的时间 当 Spring IOC 容器完成了 Bean 定义资源的定位.载入和解析注册以后,IOC 容器中已经管理类 Bean 定义的相关数据,但是此时 IOC ...

  6. Spring框架IOC容器,依赖注入,控制反转

    Spring的配制文件中 以上标签的属性id是不是必须的?不是必须的,如果定义id,那么其它的bean就可以通过此name来引用id 创建beans.xml <?xml version=&quo ...

  7. 控制反转( IoC)和依赖注入(DI)

    控制反转( IoC)和依赖注入(DI) tags: 容器 依赖注入 IOC DI 控制反转 引言:如果你看过一些框架的源码或者手册,像是laravel或者tp5之类的,应该会提到容器,依赖注入,控制反 ...

  8. Spring的控制反转(IOC)和依赖注入(DI)具体解释

    Spring的控制反转(IOC)和依赖注入(DI)具体解释 首先介绍下(IOC)控制反转: 所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的.这样控制器就有应 ...

  9. 大学生 从0开始学Spring第2篇:控制反转(IoC)与依赖注入【从0到精通】

    控制反转(IoC)与依赖注 **引出spring** 依赖关系 spring 容器 IOC:控制反转 DI:依赖注入 总结 Spring中有3个核心的概念: 控制反转(Ioc). 依赖注入(DI). ...

最新文章

  1. python中常见的数据类型_Python中常见的数据类型总结(四)
  2. 使用合成数据集来做目标检测:目标检测的介绍
  3. bootstrap的验证和确认对话框
  4. Open Train 10394
  5. properties 配置回车_在Ubuntu上部署基于Docker的RSSHub,并配置SSL证书
  6. 96秒100亿!如何抗住双11高并发流量?
  7. java long double精度丢失_long long类型转double类型部分精度丢失问题
  8. [css] 说说你对hasLayout的理解,触发hasLayout的方式有哪些?
  9. linux修改主机名(不重启)
  10. androidstudio4.1.1 build model卡主_在C++中加载PyTorch1.4的FasterRCNN模型
  11. 打印机怎么扫描到电脑_扫描全能王怎么把图片变成pdf_扫描全能王怎么把文件传到电脑上_问答...
  12. MySQL-第九篇分组和组函数
  13. c语言内存泄露检查工具,检测C++的内存泄漏用哪些工具(1)
  14. #多个基因批量cox 多因素回归cox univariate Adjust for age sex单个基因cox 回归分析 多因素 矫正年龄性别之后的cox回归分析 矫正年龄性别之后的cox生存分析
  15. 移动端性能监控方案Hertz
  16. Redis中SDS简单动态字符串
  17. 【谈判】——如何在博弈中获得更多
  18. 计算机学院新年祝福语,学院20周年祝福语
  19. 给深度学习入门者的Python快速教程 - numpy和Matplotlib篇
  20. 解决ubuntu开机变慢;删除耗时启动项

热门文章

  1. lua 获取网络时间_Lua脚本引擎教程:学习路线
  2. 设计师作品交流社区,让你的原创设计作品展示给世界
  3. 梦幻粉色空间手机背景素材,爱梦想的设计师
  4. .anonymous springsecurity需要登陆嘛_springSecurity之java配置篇
  5. Linux内核深入理解中断和异常(6):IRQs的非早期初始化
  6. Open5GS:开源5G
  7. 2018.10.22 20:10
  8. 《代码大全》程序员们怎样花费自己的时间
  9. C语言控制台窗口界面编程:用printf在终端打印一个GUI窗口
  10. php 正则表达式 文档,php的正则表达式完全手册