依赖倒置原则的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是假定所有的具体类都会变化,这也不是全对,有些具体类就相当稳定。使用这个类的客户端就完全可以依赖这个具体类而不用再弄一个抽象类。
分享到:
相关推荐
### OO设计原则 -- OO设计的 DIP依赖倒置原则 #### 概述 在软件工程领域,特别是面向对象设计中,依赖倒置原则(Dependency Inversion Principle, DIP)是六大设计原则之一,由著名软件架构师Robert C. Martin提出...
这些原则包括单一职责原则(SRP)、不要重复代码原则(DRY)、开闭原则(OCP)、里氏替换原则(LSP)、依赖倒置原则(DIP)以及接口隔离原则(ISP)。下面将详细阐述这些原则及其重要性。 1. 单一职责原则(Single ...
LSP)、依赖倒置原则(Dependency Inversion Principle,简称 DIP)以及接口隔离原则(Interface Segregation Principle,简称 ISP)。 ### 单一职责原则(SRP) **定义**:一个类应该只有一个引起它变化的原因。...
2. **依赖倒置原则**(Dependency Inversion Principle,简称DIP):高层次的模块不应该依赖于低层次的模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。这样可以降低模块间的耦合度,使得...
#### 依赖倒置原则(Dependency Inversion Principle, DIP) 依赖倒置原则要求高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。具体来说: 1. **提高模块间的...
依赖倒置原则 (DIP) 依赖倒置原则强调依赖关系应该从高层模块流向低层模块,而不是相反。具体而言,高层模块不应该依赖于低层模块的具体实现,而应该依赖于抽象;低层模块则应该依赖于高层模块提供的抽象接口。...
5. 依赖倒置原则(DIP):依赖于抽象而不是具体实现。这样可以降低模块间的耦合,提高系统的可测试性和可扩展性。 “OO Principles Explained译文.pdf”可能详细阐述了这些原则,并通过实例展示了如何在实践中应用...
5. **依赖倒置原则(Dependency Inversion Principle, DIP)** 高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象。抽象不应该依赖于具体实现,而具体实现应该依赖于抽象。这样可以降低模块间的耦合,...
#### 二、依赖倒置原则(Dependency Inversion Principle, DIP) **定义**:依赖倒置原则强调依赖于抽象而非具体实现。简单来说,高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节...
4. 依赖倒置原则(Dependency Inversion Principle, DIP) DIP强调高层模块不应该依赖于低层模块,两者都应该依赖于抽象。具体来说,依赖于接口而非实现。这样,当底层实现发生变动时,只需要修改相应的接口实现,...
DIP:依赖倒置原则 (The Dependency Inversion Principle) 依赖倒置原则同样是 Robert C. Martin 提出的,它强调高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象...
6. 依赖倒置原则(Dependence Inversion Principle - DIP) 依赖倒置原则是指高层模块不应该依赖于低层模块,它们应该依赖于抽象。这个原则强调了抽象的重要性和面向接口编程的必要性,防止类之间的紧耦合。应用时...
3. **依赖倒置原则**(DIP):依赖于抽象,而不是具体实现。这促进了模块间的解耦。 4. **接口隔离原则**(ISP):不要强迫客户端依赖它们不用的方法,提供针对性的接口。 5. **迪米特法则**(Law of Demeter):...
2. 面向对象设计原则:如单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、依赖倒置原则(DIP)和接口隔离原则(ISP)。 3. 设计模式的应用:介绍常见的设计模式,解释其工作原理和适用场景。 4. UML...
4. 依赖倒置原则(DIP):高层模块不应该依赖低层模块,而应该依赖抽象。 5. 接口隔离原则(ISP):客户端不应该依赖它不需要的接口。 6. 组合/聚合复用原则(CARP):尽量使用组合/聚合,而不是继承。 面向对象...
- 依赖倒置原则(Dependency Inversion Principle, DIP):高层模块不应该依赖于低层模块,两者都应该依赖于抽象。 设计模式是软件设计中解决特定问题的一套经验化、经过验证的最佳实践。它们不是直接用来编写代码...
4. **依赖倒置原则**(Dependency Inversion Principle, DIP):高层模块不应该依赖于低层模块,二者都应该依赖于抽象。 5. **接口隔离原则**(Interface Segregation Principle, ISP):客户端不应该被强制依赖它不...
面向对象设计的基本原则包括单一职责原则(SRP)、开放封闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)和依赖倒置原则(DIP)。这些原则指导开发者设计出灵活、可扩展和易于维护的软件。 【设计模式】 ...
此外,书中可能还会涉及面向对象设计原则,如单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、依赖倒置原则(DIP)和接口隔离原则(ISP),这些都是设计模式背后的重要理论基础。 总的来说,《设计模式--基于C#...
4. **依赖倒置原则**(Dependency Inversion Principle, DIP):高层模块不应该依赖低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。 5. **接口隔离原则**(Interface Segregation ...