关于依赖倒置,控制反转和依赖注入的趣谈

昨天经过一朋友的SPACE,看到有关于控制反转的讨论,一时技痒,写下一段留言,完后由于比较长的时间没接触这几个单词,因此又去查了些资料,重新整理了一下,跟大家一起讨论。

整理之前,首先要说说“依赖”,什么是依赖,依赖就是关联,UML中定义的“关联”是最泛泛的一种关系,表现为两个类图之间有根线就有关联,我个人理解成,在C/C++中,A include了另一个头文件B,JAVA/.Net中A using了另一个package或者unit B,则两者就有了关联,A依赖于B,因为假设没有依赖关系,A为啥要include B?肯定了发生了某种调用(B.Call())或者引用(如B做为某个类变量或者参数变量)。所以偶把这个理解成依赖。

网上讨论的假设B发生变化那A也发生变化成为依赖,偶觉得可能会有一定的误导,因为假设变化的是B内部,接口不变,那A为什么要变?或者B增加一个接口A不调用,A也不用变,但是A依然依赖于B。

这是关于依赖,接下来是关于标题三个名词,在这里不想一个个去解释,因为那可能有种就事论事的感觉,想跟大家讨论一些比较本质的东西。

在面对一个复杂事务的时候,我们的处理办法是什么?毫无疑问是分解,想想那些日理万机的领导,凡事不论巨细都要过问的话那是不可能,因为个人的精力有限,而复杂度是随着规模的增大而呈数量级的变化的,所以领导怎么处理?分解,分成市场总监,财务总监,技术总监,行政总监等一个个角色,每个角色负责一块,到时候跟领导汇报各自的问题就OK了,领导来做决策。

以软件来类比的话,这里的总监就是一个个模块,汇报就是OO中的接口(Interface),领导就是框架,把全部的模块串起来完成一个既定的大目标(如实现某个方案)。那工程师或者财务人员呢?毫无疑问就是一个个具体的CLASS了,是实现具体某个功能的执行体,如一项编程工作或者整理出某个报表。

由此可见,每天在我们周围发生的这些事情,这些公司内部的一些行为都可以映射成整个软件构架。那么从公司的这种组织行为我们可以得到什么样的思考?首先有了分解我们可以降低一些的复杂度,但接下来呢,软件最复杂的在于什么?在于变化。公司也一样,外界要面临重重生存压力,内部可能会有一些公司层面的或者个人层面的问题,甚至人员跳槽也会带来一定的风险,那公司怎么处理? 隔离。把容易变化的跟不容易变化的相对稳定的隔离开来,这样就能做到控制影响到最小。那么隔离通过什么来实现?抽象。为什么?因为抽象是相对稳定的。

这里举个比较好笑的例子:一个即将做领导的儿子问曾经做领导的父亲怎么才能平步青云,父亲说你不能说假话,因为老百姓会不答应,也不能说实话,因为领导会对你有意见,儿子思索良久问:那我该说什么? 父亲意味深长的说:空话

笑话不但好笑,还能反映一定的道理,为啥空话这么有用,因为他是抽象的,而抽象不涉及到一些具体的数据或者事务,因此他是稳定的,是不容易变化的,同时基本上也是正确的。所以我们经常在公开场合听到类似的话“我们要团结同志,努力进取,提高工作效率,降低工作成本。。。”你能说这是错的吗,当然不能,所以既然是非常稳定的对的,所以这种依赖就很可靠啦。

公司也一样,假设领导依赖于工程师的能力,成天问这个问那个,那如果有一天工程师跳槽了怎么办?领导处理的都是一些非常重要宏观的事务,不可能因为某个小小的工程师而产生什么大的影响,因此他不会直接依赖工程师,而是依赖于一个叫技术总监这样的一个抽象。如果工程师离职,那换个工程师继续替代他以前做的事情就行了,而且都实现的是技术总监规定好的接口,这样对领导就没什么影响了,也只有这样变化就被隔离开来了。

再反过来想想软件,其实上面描述的都是一些对软件而言非常有意义的做法,OO中非常重要的一点就是模块之间依赖于抽象的接口,而不是具体的实现,为啥,因为抽象是相对稳定的。一个IO他必然就有READ/WRITE这两个抽象,至于具体是磁盘还是键盘,那是下面的实现不同了,通过这种构架,能保持软件的弹性与可维护性。

由公司的行为还有一点容易受到启发的就是公司的组织构架,公司的层次可以映射成软件的分层,领导是框架层,下面通过一个个接口去管控一个个CLASS。我们设计软件的时候毫无疑问也应该这样。设计好框架设计接口,设计好接口再去调用一个个的API或者CLASS去实现某一个具体的实现比如数据库的读写或者SOCKET数据的收发。每个地方有自己相对对立的职责,各尽其职。如果上来就是一个个API,那相当于一大群工程师既做商务谈判,又去编码,那就杂乱无章啦。这样的结果感觉都是一样:混乱。

最后言归正传,谈谈上面的三个名词,依赖倒置DIP(Dependency Inversion Principle)在马丁大叔的杰作《敏捷开发:原则,实践与模式》中描述的比较清楚,高层模块不应该依赖于底层模块,而应该两者都依赖于一个抽象,底层模块实现抽象。相信这点已经在上面讨论的比较清楚了,就好比尽管领导归根结底要依赖工程师来做事,但他不会直接依赖你,而是依赖于一个总监的抽象。这就是倒置,哪里倒了?这种依赖关系倒了,引入了一个新的中间层,一个抽象。以前传统的过程设计中是从上到下的一条依赖线,现在是平的一条领导到总监,然后是一条从下往上的工程师到总监的关联线。

控制反转(Inversion of Control)其实有点类似,主要是OO中提出了框架的概念,什么是框架,按王氏兄弟的《道法自然》中的描述,主要是一个动态的环境体,可以处理一些比较复杂的事务或者逻辑,跟类库静态的行为不大一样,类库都是一个个等待别人调用的服务。 那么控制体现在什么地方?传统的做法,我们在自己的程序中调用一个个类库去完成一个个功能,类库是我们的执行体,但是逻辑算法等是自己实现的,这就是自己的控制,但框架不一样,逻辑算法都是它来实现,我们只要提供它几个需要的接口或者执行体就可。这就是反转,控制在框架这边了,主要是简化了一定的工作量,对于一些常见的业务场景不需要自己去重复实现罢了。那么控制反转主要应用的是模板方法等模式,个人觉得观察者模式是一个比较典型的控制发转的实例,因为论询observer是subject这边实现的一个逻辑,而observer 只要实现notify这样一个接口即可。所以其实也没什么。

依赖注入(Dependency Injection)其实相比以上两者应该不是一个层次的概念,主要是表现为利用构造函数或者接口来完成具体的工作类的绑定而已,这么想好了,比如要完成一个开发工作,可以让总监自己去指定工程师甲来完成这个工作,但为了更大的弹性,可以让总监提供这么个接口

AssignJob(Engineer engineer) {engineer.do();}

这样总监可以默认让甲去完成这个工作,但如果某种原因例如甲请假,那么就可以通过这个接口去让乙去做这件事情,这样在发生变化的时候就有弹性了。顺便提一下,软件多数通过CONFIG来达到更大的灵活性,由于.NET/JAVA等引入了反射的概念,可以在RUNTIME期间动态的去创建类,这个功能就很强大了,参考如上的业务需求,我们就可以把类名放在CONFIG中,通过反射去加载不同的类从而完成不同的实现。这也是很多框架(如structs)的最基本的做法

以上是一些个人看法,感觉一些OO的名词听起来玄乎,其实也就那么回事,只要掌握好OO的几个基本原则,其实基本上都可以推导出来。呵呵。个人愚见,希望跟大家交流

关于依赖倒置,控制反转和依赖注入的趣谈相关推荐

  1. 那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程...

    那些年,空气中仿佛还能闻到汉唐盛世的余韵,因此你决不允许自己的脸上有油光,时刻保持活力.然而,你一定曾为这些"高深术语"感到过困扰--依赖倒置•控制反转•依赖注入•面向接口编程.也 ...

  2. 那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程【转】...

    那些年,空气中仿佛还能闻到汉唐盛世的余韵,因此你决不允许自己的脸上有油光,时刻保持活力.然而,你一定曾为这些"高深术语"感到过困扰.也许时至今日,你仍对它们一知半解.不过就在今天, ...

  3. 高深术语——依赖倒置•控制反转•依赖注入•面向接口编程

    今天,我将带领你以一种全新的高清视角进入奇妙的编程世界,领略涵泳在这些"高深术语"中的活泼泼的地气,以及翩跹于青萍之末的云水禅心. 高聚合·低耦合 简短:管理好自己(内聚),但是有 ...

  4. 【转】那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程

    作者:在好 链接:https://www.zhihu.com/question/31021366/answer/102239756 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  5. Software--IoC 依赖倒置 控制反转

    软件开发设计原则 S.O.L.I.D 中的 Idependence Convert 转载于:https://www.cnblogs.com/masterSoul/p/7849519.html

  6. 架构设计之依赖倒置、控制反转与依赖注入

    名词解释 依赖:一种模型元素之间的关系的描述.例如类A调用了类B,那么我们说类A依赖于类B. 耦合:一种模型元素之间的关系的描述.例如类A调用了类B或类B调用了类A,那么我们说类A与类B有耦合关系. ...

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

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

  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 ...

  10. Spring控制反转和依赖注入的好处

    要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则(Dependency Inversion Principle ). 什么是依赖 ...

最新文章

  1. 安装pyspider后运行pyspider all后遇到的问题
  2. Java里main的写法_main方法的深入理解和例子
  3. MongoDB 基础用法及学习笔记
  4. appium java版本错误_java – 无法创建新会话. appium代码中的错误
  5. html5列表去掉符号,从Python字符串中删除不在允许列表中的HTML标记
  6. 欢迎使用Augury[翻译]
  7. python 廖雪峰数据分析统计服_廖雪峰Python总结1
  8. java file ip_java常用工具类 IP、File文件工具类
  9. New StoryBoard in iOS9
  10. java jdk 文档下载_JDK8 API文档(下载)
  11. 快速提升网站排名的七种方法
  12. php eval函数的用法,php eval函数用法详解
  13. 音视频开发第一课-使用C语言开发视频播放器 650元IT外包开发全程记录
  14. 水星mr807虚拟服务器,水星MR807路由器怎么连接Internet上网
  15. 马克鳗标记及文字图片工具安装步骤mac版本
  16. 生成带有logo的二维码
  17. 超牛叉技术支撑的成人网站
  18. 接口测试工具Postman的基本使用
  19. 【xdoj难题集】1039: 饭桌上的游戏
  20. html5将数组转换为字符串,js如何将数组元素转换为字符串

热门文章

  1. PDF Expert mac使用教程:压缩pdf文件大小
  2. 【Flutter】Dart的方法与箭头函数
  3. HashSet、LinkedHashSet和TreeSet三者区别与联系
  4. Docker 容器十诫
  5. OA选型案例:建筑行业选型华天OA系统
  6. 今年的移动Pwn2own破解大赛:iPhone+安卓=50万美元
  7. MVC4使用SignalR出现$.connection is undefined错误备忘
  8. Mysql 慢查询和慢查询日志分析
  9. 「leetcode」栈与队列:总结篇!
  10. UNIX环境高级编程之第6章:系统数据文件和信息