象的控制权交由配置文件控制,然后根据配置文件中的信息(程序集+类型),通过反射来获取对象,而不是直接new对象,这也是控制反转的一种体现。

IoC容器会连接程序中的所有模块,模块将所需对象的控制权都交由IoC容器控制,IoC容器会根据用户配置的信息将各个模块所需要的对象事先创建完成,然后IoC容器可以通过依赖注入(DI)的方式为模块注入所需对象(还有依赖查找(DL)),依赖注入就是一种具体实现的手段。

依赖倒置原则、控制反转和依赖注入并不是为程序带来新的功能,而是使得程序中模块的耦合性降低,提高每个模块的复用性。

举个栗子:

就拿生活中最常见的自助取款机来说一下,首先我们要拥有一张银行卡,例如建设银行的银行卡CCBCard类(设计的一些属性可能不太合理,不过重要的是了解思想)

//建行银行卡public class CCBCard{//银行卡中的钱public decimal Money { get; set; }

//银行卡名字public String Name { get; set; }

public CCBCard(decimal money,String name)    {this.Money = money;this.Name = name;    }}

然后我们来创建一个ATM自动取款机类,该取款机拥有取钱和存钱的功能

ATM机1.0

//自动取款机public class ATM{//建行银行卡public CCBCard Card = new CCBCard(1000,"建行卡");

//取钱public void SubMoney(decimal money)    {//判断余额是否足够if (Card.Money >= money)        {//取钱this.Card.Money -= money;            Console.WriteLine($"取钱成功,余额{Card.Money}");        }else {            Console.WriteLine("余额不足");        }    }

//存钱public void AddMoney(decimal money)    {//存钱this.Card.Money += money;    }}

因为这个例子是生活中非常常见的,所以大家肯定一眼就看出了不妥

此时的ATM机可是说是个非常“睿智”的ATM机了,我去取钱,而ATM机却自带了一张建行银行卡,与其说是个ATM机,倒不如说只能对一个CCBCard建行卡进行存取的机器。此时ATM类完全依赖于CCBCard对象,而且CCBCard对象也是由ATM类创建的,如果CCBCard修改了,或者要换其他的卡,ATM机还要做出修改。

所以接下来我们应该将这不好的两点改掉:

1、ATM机只能读取单一的CCBCard卡(ATM控制CCBCard对象的创建)

2、ATM只能读取CCBCard类型的卡(ATM完全依赖于CCBCard对象)

先来解决第一点,接下来我们改进一下,为ATM机增加构造函数,通过构造函数传递CCBCard对象,使得ATM机可以操作其他建行卡:

ATM机2.1:

增加构造函数,两个方法不用变

//建行银行卡public CCBCard Card;

//构造函数传入CCBCard对象public ATM(CCBCard card){this.Card = card;}

使用:

//银行卡CCBCard card = new CCBCard(1000,"建行卡");//ATMATM atm = new ATM(card);//取钱atm.SubMoney(100);

然后来解决第二个问题,只能存取建行卡:

此时就需要用到依赖倒置原则,让ATM类依赖于CCBCard抽象,而不是具体的实现。如果我们想存取其他银行卡里面的钱,必须为所有的银行卡抽象出一个接口,然后让所有银行卡子类都实现这个接口。

//银行卡接口public interface ICard{string Name { get; set; }decimal Money { get; set; }}

建行卡实现该接口:

//建行银行卡public class CCBCard:ICard{//银行卡中的钱public decimal Money { get; set; }

//银行卡名字public String Name { get; set; }

public CCBCard(decimal money,String name)    {this.Money = money;this.Name = name;    }}

使得ATM机依赖于ICard接口(修改了Card属性和构造函数),而且ATM机并不控制ICard的子类,而是将控制权交由调用者。这一切才合情合理啊,无论用户插入什么卡,该ATM机都能进行存取。这就是控制反转,而通过构造函数传入的ICard对象则是通过依赖注入的方式注入对象。

//建行银行卡public ICard Card;

//构造函数传入ICard对象(依赖注入)public ATM(ICard card){this.Card = card;}

依赖注入还有其他两种:通过接口和属性注入

//属性注入public ICard Card { get; set; }
//接口注入//该方法实现了接口public void Inject(ICard card){this.Card = card;}

而接口注入就是通过方法注入,此种方式会增加不必要的接口,现在基本不使用,大多为构造函数注入。

新添加一个ICBC(工商银行)卡进行测试

//工商银行卡public class ICBCCard : ICard{public string Name { get; set; }public decimal Money { get; set; }}

测试:

//建设银行卡CCBCard bcard = new CCBCard(1000, "CCB");//工商银行卡ICBCCard ccard = new ICBCCard(){    Money = 1000,    Name = "ICBC"};

//ATMATM atm1 = new ATM(bcard);ATM atm2 = new ATM(ccard);//取钱atm1.SubMoney(100);

IoC容器就是专门为ATM机这种模块服务的,它就像是一个大齿轮一样,连接所有小齿轮(模块),它运转,整个程序便运转,如果有些模块可能需要用到其他模块中的对象,它们并不会直接依赖,而是全都由IoC容器控制。

虽然互相需要,但是互不依赖,IoC容器会事先将ICard子类创建好,然后通过依赖注入注入到ATM机中(Unity、Spring.NET等框架都是封装完善的IoC容器),ATM机只管接收,只管索取。ATM机是不对子类进行创建的,控制权在用户手里,由用户控制ATM机操作何种银行卡,就像你去取钱一样,你插入什么卡自助取款机都可以取钱,这看起来是多么平常的一件事?很多看起来高大上的思想,都是从需求演变过来的,然后由前人一点点探索研究总结出来。

至此ATM机已经完成了,可能因为ATM机太常见了,所以我所说的一切你都可以想到(换卡,换不同银行的银行卡),就像是在说废话,如果你都理解了,那么根据ATM机,你应该仔细的思索一下,你所设计的类和模块满不满足像ATM机一样的“功能”?

原文链接:https://www.cnblogs.com/ckka/p/11448065.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

依赖倒置原则(DIP)、控制反转(IoC)、依赖注入(DI)(C#)相关推荐

  1. 依赖倒置(DIP),控制反转(IoC)与依赖注入(DI)

    DIP,IoC与DI概念解析 依赖倒置 DIP(Dependency Inversion Principle) DIP的两大原则: 1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象. 2.抽象不 ...

  2. C#软件设计——小话设计模式原则之:依赖倒置原则DIP

    前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做" ...

  3. 吐槽 依赖倒置原则/DIP

    返回目录   1.2.5抛弃依赖倒置原则(正文) ,本文专门吐槽依赖倒置原则(Dependency Inversion Principle.DIP). 1.Robert C. Martin的那篇DIP ...

  4. 7.12 其他面向对象设计原则3: 依赖倒置原则DIP

    其他面向对象设计原则3: 依赖倒置原则DIP  The Dependency Inversion Principle 7.1 依赖倒置原则DIP The Dependency Inversion P ...

  5. 【简译】关于依赖反转原则、控制反转和依赖注入的抽象的初学者指南

    原文在此. ======================================分割线==================================== 介绍 文章以介绍依赖反转原则开始 ...

  6. 依赖倒置、控制反转、依赖注入

    实现依赖倒置.控制反转.依赖注入的核心思想是:接口驱动 接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性,实现模块之间的解耦等等. 参考资料:https://www.cnblogs ...

  7. java-12:spring MVC - 控制反转IOC,依赖注入DI

    学习spring框架之前,先理解几个概念: 1.第一部分:依赖倒置原则 2.第二部分:控制反转,控制反转容器(实例) 3.第三部分:控制反转,控制反转容器(全面理解,面试题) 综合性理解:控制反转(I ...

  8. php程序设计依赖注入_PHP控制反转和依赖注入

    [TOC] PHP和依赖注入 理论知识 要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则(Dependency Inversio ...

  9. 一篇文章讲透控制反转和依赖注入

    https://www.jianshu.com/p/07af9dbbbc4b 转载链接:http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/# http ...

最新文章

  1. 本地缓存性能之王Caffeine
  2. java for 删除 list 中的项
  3. 【深度学习】Transfomer在文本处理上的应用(风格识别)
  4. 俄罗斯方块新增行算法:不拘一格编程序之二
  5. 排序的概念(选择排序1)
  6. 2013\National _C_C++_C\1.好好学习
  7. Kali 2.0 采用ssh连接登陆
  8. STM32学习之路-SysTick的应用(时间延迟)
  9. tomcat jsvc java_opts_Tomcat 学习笔记(2) - 使用 jsvc 启动tomcat
  10. 中小学计算机教学大纲,中小学信息技术教材教法教学大纲
  11. python手机安装模块_python如何安装模块 模块安装操作教程
  12. centos7.4下安装mysql_Linux(Centos7.4)服务器下安装mysql
  13. 微信小程序生成小程序码,如何在开发版本调试?
  14. 我的内核学习笔记5:proc目录文件创建及读写
  15. 汇编的接触——基础知识
  16. 我的javascript学习笔记之数据类型
  17. 如何搭建点燃式发动机仿真模型
  18. 字体反爬案例解析:大众点评
  19. 女人喝酸奶要注意什么
  20. 【题解】【LibreOJ Round #6】花团 LOJ 534 时间线段树分治 背包

热门文章

  1. 直播源码中有哪些网络协议需要注意?
  2. Javascript基础之-Promise
  3. 12C RAC for ASM添加磁盘步骤
  4. 898A. Rounding#数的舍入
  5. MongoDB 3.0 新增特性一览
  6. SDN火爆!未来五年年复合增长率达98%
  7. 如何在画面中摆放大量图片
  8. SegmentFault 创始人祁宁对话 C# 之父 Anders Hejlsberg
  9. 深入分析Volatile的实现原理
  10. Win7 Ubuntu13.04互通(win7下用vbox安装Ubuntu)