编程模式---依赖倒转原则(DIP)

     实现“开-闭”原则的关键是抽象化,并且从抽象化导出具体化实现。如果说“开-闭”原则是面向对象设计的目标的话,依赖倒转原则就是这个面向对象设计的主要机制。依赖倒转原则讲的是:要依赖于抽象类,不要依赖于具体

一、为何而“倒转”

   简单的说,传统的过程性系统的设计办法倾向于使高层次的模块依赖于低层次的模块:抽象层次依赖于具体层次。倒转原则是要把这个错误的依赖关系倒转过来,这就是“依赖倒转原则”的由来。

     抽象层次依赖于具体层次的含义是什么呢?抽象层次包含的是应用系统的商务逻辑和宏观的。对整个系统来说重要的战略性决定,是必然性的体现;而具体层次则含有一些次要的与实现有关的方法和逻辑,以及战术性的决定,带有相当大的偶然性选择。具体层次的代码是会经常变动的,不能避免出现错误。抽象层次依赖于具体层次,使许多具体层次的细节的算法变化立即响应到抽象层次的宏观商务逻辑,这导致微观决定宏观,战术决定战略,偶然决定必然,这岂不是很荒唐。

     抽象层次依赖于具体层次显然是不对的。依赖倒转原则就是要把错误的依赖关系倒转过来。依赖倒转原则是COM、CORBA、JavaBean以及EJB等构件模型背后的基本原则。

二、复用和可维护性的“倒转”

    从复用的角度来看,高层次的模块是设计者应当复用的。但是在传统的过程性的设计中,复用却侧重于具体层次模块的复用,比如算法的复用、数据结构的复用、函数库的复用等,都不可避免是具体层次模块的复用。较高曾侧的结构依赖于较低层次的结构,较低层次的结构又进一步依赖于更低层次的结构,如此继续。较低层次上的修改,会造成较高层次的修改,直到高层次逻辑的修改。

    同样,传统的做法也强调具体层次上的可维护性,包括一个函数、数据结构等可维护性,而不是高层次上的可维护性。

     从复用的意义上讲,既然抽象层次含有一个应用系统最重要的宏观商务逻辑,是做战略判断和决定的地方,那么抽象层次应当是较为稳定的,应当是复用的重点。由于现有的复用侧重于具体模块和细节的复用,因此,“倒转”一词则是指复用应当将复用的重点放在抽象层次上。如果抽象层次的模块相对独立于具体层次的模块的话,那么抽象层次的模块的复用便是相对较为容易的了。

     同样,最重要的宏观商务逻辑也应当是维护的重点,而不是相反。因此,遵守依赖倒转原则会带来复用和可维护性的“倒转”。

三、依赖倒转原则

1、依赖(或者耦合)关系的种类。

     在面向对象的系统里,两个类之间可以发生三种不同的耦合关系:

     ①零耦合关系:如果两个类没有耦合关系,就称为零耦合;

     ②具体耦合关系:具体性耦合发生在两个具体的(可实例化的)类之间,经由一个类对另一个类的直接引用造成。

     ③抽象耦合关系:抽象耦合关系发生在一个具体类和一个抽象类(或者Java接口)之间,使两个必须发生关系的类之间存在更大的灵活性。

2、依赖倒转原则

     简单的说,依赖倒转原则要求客户端依赖于抽象耦合。依赖倒转原则的表述是:抽象不应当依赖于细节;细节应当依赖于抽象。另一种表述是:要针对接口编程,不要针对实现编程。

     ①针对接口编程的意思就是说,应当使用接口和抽象类进行变量的类型声明、参量的类型声明、方法的返还类型声明,以及数据类型的转换等。

     ②不要针对实现编程的意思是说,不应当使用具体Java类进行变量的类型声明、参量的类型声明、方法的返还类型声明,以及数据类型的转换等。

     要保证做到这一点,一个具体Java类应当只实现接口和抽象类中声明过的方法,而不应当给出多余的方法。倒转依赖关系强调一个系统的实体之间关系的灵活性。基本上,如果我们希望遵守“开-闭”原则,那么倒转依赖原则便是达到要求的途径。

3、总结

     以抽象方式耦合是依赖倒转原则的关键。由于一个抽象耦合关系总是要涉及具体类从抽象类继承,并且需要保证在任何引用到基类的地方都可以改换成其子类,因此,里氏代换原则是依赖倒转原则的基础。

     依赖倒转原则是OO设计的核心原则,设计模式的研究和应用是以依赖倒转原则为指导原则的。

4、注意

     一般而言,在创建一个对象时,Java要求使用new关键字以及这个类本身。而一旦这个对象被创建出来,那么就可以灵活使用这个对象的抽象类型来引用它。因此,Java语言中创建一个对象的过程是违背“开-闭”原则以及依赖倒转原则的。虽然在这个类被创建出来以后,可以通过多态性使得客户端依赖于抽象类型。

    正式这个原因,设计模式给出了多个创建模式,特别是工厂模式。用于解决对象创建过程中的依赖倒转问题。其他还可以解决该问题的模式还有模板模式、迭代模式等。

四、墨子论道

     《墨子·小取》中说:“爱人,待周爱人而后为爱人”。换言之,如果“爱人”是一个行为的话,这个行为对所有的人成立。因此,“爱人”之人是抽象之人,所有具体之人皆是抽象“人”的子类型,所以爱人的行为对所有的子类型成立。因此,“取周”便是抽象依赖之意,抽象的依赖使得“爱人”行为对所有的人,包括见过的和没有见过的人都成立。

五、依赖倒转原则的优缺点

     依赖倒转原则虽然很强大,但却是最不容易实现的。因为依赖关系倒转的缘故,对象的创建很可能要使用对象工厂,以避免对具体类的直接引用,此原则的使用还会导致大量的类,对不熟悉面向对象的人来说,维护这样的系统需要较好的面向对象的设计知识。

    此外,依赖倒转原则假定所有的具体类都是会变化的,这也不总是正确的。有一些具体类可能是相当稳定、不会发生变化的,消费这个具体类实例的客户端完全可以依赖于这个具体类型,而不必为此发明一个抽象类。

 

 

本文通过总结《java与模式》而来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值