在传统的自顶向下、自底向上的编程思想中,通过对模块的分层形成不同层次的模块,最上层的模块通常都要依赖下面的子模块来实现,从而就形成了高层依赖底层的结构
“过分”地依赖于底层模块意味着很难得到有效的复用。底层模块的修改将直接影响到其上层的各类应用模块,从而散发“脆弱性”的“臭味”。依赖倒置原则(The Dependency Inversion Principle, DIP)为这种依赖层次的设计提供了一种新思路。
基本思路
DIP基本思路就是要逆转传统的依赖方向,使高层模块不再依赖底层模块,从而建立一种更合理的依赖层次。该原则可以套用下面两段话来描述。
- 高层模块不应该依赖于底层模块,两者都应该依赖于抽象。
- 抽象不应该依赖于细节,细节应依赖于抽象。
该原则核心的思想就是“依赖于抽象”。这是因为抽象的事物不同于具体的事物,抽象的事物发生变化的频率要低,让高层模块与底层模块都依赖于一个比较稳定的事物比去依赖一个经常发生变化的事物的好处是显而易见的。在具体实现时,就是多使用接口与抽象类,而少使用具体的实现类。利用这些抽象将高层模块(如一个类的调用者)与具体的被操作者(如一个具体类)隔离开,从而使具体类在发生变化时不至于对调用者产生影响。
高层和底层之间没有直接的依赖关系,而是都依赖于重新定义的抽象层;原有的自上而下的依赖关系被倒置为都依赖于抽象层。
由DIP的定义,按照“依赖止于抽象”(即程序中所有依赖关系都应该终止于抽象类或接口)的思想,可以得出如下所示的启发式规则。
- 任何变量都不应该持有一个指向具体类的指针或者引用。
- 任何类都不应该从具体类派生(始于抽象,来自具体)。
- 任何方法都不应该修改它的任何基类中的、已经实现的方法
在Java企业级应用开发中,就提供了支持DIP实现的容器,如Spring框架(在Java中称为IoC容器)。在该框架中,通过XML配置文件建立接口和具体类之间的关系,IoC容器通过该配置文件来做具体的新建的工作,这样在实际应用中,只需要修改配置文件就能换成不同的具体类,从而不需要修改任何代码了。为了便于理解DIP的设计思想和实现方