OO设计原则 -- Dependency Inversion Principle:OO设计的 DIP依赖倒置原则
依赖倒置原则的2个重要方针
A. High level modules should not depend upon low level modules. Both shoulddepend upon abstractions.
高层模块不应该依赖于低层模块,二者都应该依赖于抽象
B. Abstractions should not depend upon details. Details should depend uponabstractions.
抽象不应该依赖于细节,细节应该依赖于抽象
概念解说:
依赖:在程序设计中,如果一个模块a使用/调用了另一个模块b,我们称模块a依赖模块b。
低层模块:往往在一个应用程序中,我们有一些低层次的类,这些类实现了一些
基本的或初级的操作,我们称之为低层模块;
高层模块:另外有一些高层次的类,这些类封装了某些复杂的逻辑,并且依赖于
低层次的类,这些类我们称之为高层模块。
我们现在来看看依赖有几种,依赖也就是耦合,分为下面三种:
----- 零耦合(Nil Coupling)关系,两个类没有依赖关系,那就是零耦合。
----- 具体耦合(Concrete Coupling)关系,两个具体的类之间有依赖关系,
那么就是具体耦合关系,如果一个具体类直接引用另外一个具体类就会发
生这种关系。
-----抽象耦合(Abstract Coupling)关系,这种关系发生在一个具体类和一个抽
象类之间,这样就使必须发生关系的类之间保持最大的灵活性。
为什么叫做依赖倒置(DependencyInversion)呢?
面向对象程序设计相对于面向过程(结构化)程序设计而言,依赖关系被倒置了。因为传统的结构化程序设计中,高层模块总是依赖于低层模块。
依赖倒置(Dependence InversionPrinciple)原则讲的是:要依赖于抽象,不要依赖于具体。
简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:
抽象不应当依赖于细节;细节应当依赖于抽象;
要针对接口编程,不针对实现编程。
问题的提出
Robert C. Martin氏在原文中给出了“Bad Design”的定义:
1. It is hard to change because every change affects too many other parts ofthe system.(Rigidity)
系统很难改变,因为每个改变都会影响其他很多部分。
2. When you make a change, unexpected parts of the system break. (Fragility)
当你对某地方做一修改,系统的看似无关的其他部分都不工作了。
3. It is hard to reuse in another application because it cannot be disentangledfrom the current application. (Immobility)
系统很难被另外一个应用重用,因为你很难将要重用的部分从系统中分离开来。
导致“Bad Design”的很大原因是“高层模块”过分依赖“低层模块”。
一个良好的设计应该是系统的每一部分都是可替换的。
如果“高层模块”过分依赖“低层模块”:
一方面一旦“低层模块”需要替换或者修改,“高层模块”将受到影响;
另一方面,高层模块很难可以重用。
比如,一个Copy模块,需要把来自Keyboard的输入复制到Print,
即使对Keyboard和Print的封装已经做得非常好,但如果Copy模块里直接使用Keyboard与Print,
Copy任很难被其他应用环境(比如需要输出到磁盘时)重用。
问题的解决:
为了解决上述问题,Robert C. Martin氏提出了OO设计的Dependency Inversion Principle (DIP) 原则。
DIP给出了一个解决方案:
在高层模块与低层模块之间,引入一个抽象接口层。
High Level Classes(高层模块) -->
Abstraction Layer(抽象接口层) -->
Low Level Classes(低层模块)
抽象接口是对低层模块的抽象,低层模块继承或实现该抽象接口。
这样,高层模块不直接依赖低层模块,高层模块与低层模块都依赖抽象接口层。
当然,抽象也不依赖低层模块的实现细节,低层模块依赖(继承或实现)抽象定义。
Robert C. Martin氏给出的DIP方案的类的结构图:
PolicyLayer -->
MechanismInterface(abstract) -->
MechanismLayer -->
UtilityInterface(abstract) -->
UtilityLayer
类与类之间都通过Abstract Layer来组合关系。
实例说明DIP
反面例子:
缺点:耦合太紧密,Light发生变化将影响ToggleSwitch。
解决办法一:
将Light作成Abstract,然后具体类继承自Light。
优点:ToggleSwitch依赖于抽象类Light,具有更高的稳定性,而BulbLight与TubeLight继承自Light,可以根 据"开放-封闭"原则进行扩展。只要Light不发生变化,BulbLight与TubeLight的变化就不会波及ToggleSwitch。
缺点:如果用ToggleSwitch控制一台电视就很困难了。总不能让TV继承自Light吧。
解决方法二:
优点:更为通用、更为稳定。
总结
DIP要求客户端依赖于抽象耦合,抽象不应当依赖于细节,细节应当依赖于抽象(Abstractionsshould not depend upon details. Details should depend upon abstractions),这 个原则的另外一个表述就是"四人团"强调的那个:要针对接口编程,不要对实现编程(Program to aninterface, not an implementation),程序在需要引用一个对象时,应当尽可能的使用抽象类型作为变量的静态类型,这就是针对接口编程的含义。DIP是达到"开-闭"原则的途径。
要做到DIP,用抽象方式耦合是关键。由于一个抽象耦合总要涉及具体类从抽象类继承。并且需要保证在任何引用到某类的地方都可以改换成其子类,因此,LSP是DIP的基础。DIP是OOD的核心原则,设计模式的研究和应用都是用它作为指导原则的。DIP虽然强大,但是也很难实现。另外DIP是假定 所有的具体类都会变化,这也不是全对,有些具体类就相当稳定。使用这个类的客户端就完全可以依赖这个具体类而不用再弄一个抽象类。
- 1社会化营销,我们犯的那些错误
- 2海底捞的人文化营销
- 3查理的厨房微博营销
- 4给客户打电话的营销技巧
- 5四大社交媒体 四种营销策略
- 6加多宝大战王老吉的营销启示
- 7快乐营销:心态、心境、心势的统筹
- 8解析传媒营销管理的七大误区
- 9如何正确进行邮件营销A/B Test
- 10教你一招:客户管理和沟通方法
- 11营销策划:三只松鼠的营销技巧
- 12会展企业获取用户信息,提高营销精准度策略
- 13营销战略选择
- 14产品营销中的南风法则
- 15盘点:十大营销经典案例
- 16企业销售信息化管理工具介绍
- 17恋爱,成了再追;营销,赢了再打
- 18看必胜客玩转话题营销
- 19市场营销:发现、保留和培育顾客的艺术
- 20旅游营销如何加载创意
- 21浅析企业如何社会化营销以及搜索营销
- 22哈佛经典:为营销模式纠偏
- 23营销与发展的实质反观
- 24深度营销:营销组织与管理模式的转型
- 25项目型商业销售管理软件系统的应用与价值
- 26新媒体营销现状及解决之道
- 27创业型快消品企业营销策划创造实绩五秘诀
- 28?óòμ?¢D?óa?ú??è?o?íú?ò??×?ó??§
- 29说说营销的神秘感
- 30新时代的营销创新