当前位置:首页>管理咨询>OO设计原则 -- Dependency Inversion Principle:OO设计的 DIP依赖倒置原则 查询:
     
OO设计原则 -- Dependency Inversion Principle:OO设计的 DIP依赖倒置原则
依赖倒置原则的2个重要方针

A.Highlevelmodulesshouldnotdependuponlowlevelmodules.Bothshoulddependuponabstractions.

高层模块不应该依赖于低层模块,二者都应该依赖于抽象
B.Abstractionsshouldnotdependupondetails.Detailsshoulddependuponabstractions.
抽象不应该依赖于细节,细节应该依赖于抽象

概念解说:

依赖:在程序设计中,如果一个模块a使用调用了另一个模块b,我们称模块a依赖模块b。

低层模块:往往在一个应用程序中,我们有一些低层次的类,这些类实现了一些

基本的或初级的操作,我们称之为低层模块;

高层模块:另外有一些高层次的类,这些类封装了某些复杂的逻辑,并且依赖于

低层次的类,这些类我们称之为高层模块。

我们现在来看看依赖有几种,依赖也就是耦合,分为下面三种:

-----零耦合(NilCoupling)关系,两个类没有依赖关系,那就是零耦合。

-----具体耦合(ConcreteCoupling)关系,两个具体的类之间有依赖关系,

那么就是具体耦合关系,如果一个具体类直接引用另外一个具体类就会发

生这种关系。

-----抽象耦合(AbstractCoupling)关系,这种关系发生在一个具体类和一个抽

象类之间,这样就使必须发生关系的类之间保持最大的灵活性。


为什么叫做依赖倒置(DependencyInversion)呢?
面向对象程序设计相对于面向过程(结构化)程序设计而言,依赖关系被倒置了。因为传统的结构化程序设计中,高层模块总是依赖于低层模块。

依赖倒置(DependenceInversionPrinciple)原则讲的是:要依赖于抽象,不要依赖于具体。

简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:

抽象不应当依赖于细节;细节应当依赖于抽象;

要针对接口编程,不针对实现编程。

问题的提出

RobertC.Martin氏在原文中给出了“BadDesign”的定义:
1.Itishardtochangebecauseeverychangeaffectstoomanyotherpartsofthesystem.(Rigidity)
系统很难改变,因为每个改变都会影响其他很多部分。
2.Whenyoumakeachange,unexpectedpartsofthesystembreak.(Fragility)
当你对某地方做一修改,系统的看似无关的其他部分都不工作了。
3.Itishardtoreuseinanotherapplicationbecauseitcannotbedisentangledfromthecurrentapplication.(Immobility)
系统很难被另外一个应用重用,因为你很难将要重用的部分从系统中分离开来。

导致“BadDesign”的很大原因是“高层模块”过分依赖“低层模块”。
一个良好的设计应该是系统的每一部分都是可替换的。
如果“高层模块”过分依赖“低层模块”:

一方面一旦“低层模块”需要替换或者修改,“高层模块”将受到影响;

另一方面,高层模块很难可以重用。

比如,一个Copy模块,需要把来自Keyboard的输入复制到Print,

即使对Keyboard和Print的封装已经做得非常好,但如果Copy模块里直接使用Keyboard与Print,

Copy任很难被其他应用环境(比如需要输出到磁盘时)重用。

问题的解决:

为了解决上述问题,RobertC.Martin氏提出了OO设计的DependencyInversionPrinciple(DIP)原则。

DIP给出了一个解决方案:

在高层模块与低层模块之间,引入一个抽象接口层。


HighLevelClasses(高层模块)--

AbstractionLayer(抽象接口层)--

LowLevelClasses(低层模块)


抽象接口是对低层模块的抽象,低层模块继承或实现该抽象接口。
这样,高层模块不直接依赖低层模块,高层模块与低层模块都依赖抽象接口层。
当然,抽象也不依赖低层模块的实现细节,低层模块依赖(继承或实现)抽象定义。

RobertC.Martin氏给出的DIP方案的类的结构图:


PolicyLayer--

MechanismInterface(abstract)--

MechanismLayer--

UtilityInterface(abstract)--

UtilityLayer


类与类之间都通过AbstractLayer来组合关系。

实例说明DIP

反面例子:


缺点:耦合太紧密,Light发生变化将影响ToggleSwitch。

解决办法一:
将Light作成Abstract,然后具体类继承自Light。


优点:ToggleSwitch依赖于抽象类Light,具有更高的稳定性,而BulbLight与TubeLight继承自Light,可以根据"开放-封闭"原则进行扩展。只要Light不发生变化,BulbLight与TubeLight的变化就不会波及ToggleSwitch。

缺点:如果用ToggleSwitch控制一台电视就很困难了。总不能让TV继承自Light吧。

解决方法二:



优点:更为通用、更为稳定。

总结

DIP要求客户端依赖于抽象耦合,抽象不应当依赖于细节,细节应当依赖于抽象(Abstractionsshouldnotdependupondetails.Detailsshoulddependuponabstractions),这个原则的另外一个表述就是"四人团"强调的那个:要针对接口编程,不要对实现编程(Programtoaninterface,notanimplementation),程序在需要引用一个对象时,应当尽可能的使用抽象类型作为变量的静态类型,这就是针对接口编程的含义。DIP是达到"开-闭"原则的途径。

要做到DIP,用抽象方式耦合是关键。由于一个抽象耦合总要涉及具体类从抽象类继承。并且需要保证在任何引用到某类的地方都可以改换成其子类,因此,LSP是DIP的基础。DIP是OOD的核心原则,设计模式的研究和应用都是用它作为指导原则的。DIP虽然强大,但是也很难实现。另外DIP是假定所有的具体类都会变化,这也不是全对,有些具体类就相当稳定。使用这个类的客户端就完全可以依赖这个具体类而不用再弄一个抽象类。



企业社会化媒体营销必知的那些事经销商一体化营销之路
口碑营销内容设计五要素如何进行第三终终端信息传播
性格决定销售风格—销售经理必读SPIN,敲定大订单
匹克:围绕消费者进行营销变革丁兴良:中国铝业的冬天何时才能过去
“史大嘴”:新行长应该公开招聘卖场和采购眼中的“大红人”是怎样炼成的
商场施恩计-如何建立顾客营销的三条创新发展之路
营销,也要讲究一寸长一寸强政府采购中,供应商的利益谁来保证?
企业主如何看待如火的微信经销商品类霸主营销之路
信息发布:广州名易软件有限公司 http://www.myidp.net

  • 名易软件销售服务
  • 名易软件销售服务
  • 名易软件技术服务

  • OO设计原则 -- Dependency Inversion Principle:OO设计的 DIP依赖倒置原则,OO设计原则 -- Dependency Inversion Principle:OO设计的 DIP依赖倒置原则