设计原则(四)依赖倒置原则(DIP)

一、什么是依赖倒置原则

一种表述:
抽象不应当依赖于细节;细节应当依赖于抽象。

另一种表述:
要针对接口编程,不要针对实现编程。

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

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

二、为什么要倒置

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

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

三、再看工厂方法模式

按照依赖倒置原则,客户端应该依赖于对象的抽象类型而不是它的具体类型,但是在Java中使用new创建一个具体对象实例时必须调用具体类的构造方法,所以Java语言给出的类的实例无法做到只依赖于抽象类型。但是我们可以做到部分依赖,因为Java中有多态的特性。例如A是一个抽象类,B是继承自A的一个具体子类,我们可以写如下的代码:

B b = new B();

这是一个完全依赖具体的不好的写法,我们可以利用多态性写成下面这样:

A a = new B();

这样就变成了部分依赖,前边的A是依赖于抽象的,这样当B换成其他的继承自A的子类的时候,其他的程序是不会受到影响的。即使是这样还是没有做到完全依赖于抽象,在设计模式中前边讲过的工厂方法模式就解决了这个问题。

工厂方法模式将创建一个对象的工程封装起来,客户端仅仅得到这个实例化的结果,以及这个实例的抽象类型,当然工厂方法也不能避免要用new创建对象的限制,但是工厂模式将这个违反规则的做法推迟到了具体工厂角色中。将违反规则的做法孤立于易于控制的地方。

四、实例分析

这是一个银行账户的例子,一个Account包含两个部分,AccountType和AccountStatus,这两个类都是抽象类,这两个类分别有两个具体的子类,Account在使用的是抽象类而不是子类,从而在Account的角度上是符合依赖倒置原则的。

package com.designphilsophy.dip;
/**
 * 账户
 * @author xingjiarong
 *
 */
public class Account {

    private AccountType accountType;
    private AccountStatus accountStatus;

    public Account(AccountType acctType) {
        // write your code here
    }

    public void deposit(float amt) {
        // write your code here
    }

}
package com.designphilsophy.dip;

/**
 * 账户的状态是开的状态还是超支状态
 * @author xingjiarong
 *
 */
public abstract class AccountStatus
{
    public abstract void sendCorrespondence();
}
package com.designphilsophy.dip;

/**
 * 账户的类型是储蓄卡还是支票
 * 
 * @author xingjiarong
 *
 */
public abstract class AccountType {
    public abstract void deposit(float amt);
}
package com.designphilsophy.dip;

/**
 * 支票
 * 
 * @author xingjiarong
 *
 */
public class Checking extends AccountType {
    public void deposit(float amt) {
        // write your code here
    }
}
package com.designphilsophy.dip;

/**
 * 储蓄卡
 * 
 * @author xingjiarong
 *
 */
public class Savings extends AccountType {
    public void deposit(float amt) {
        // write your code here
    }
}
package com.designphilsophy.dip;

/**
 * 开状态
 * 
 * @author xingjiarong
 *
 */
public class Open extends AccountStatus {
    public void sendCorrespondence() {
        // write your code here
    }
}

在这个例子中,Account类依赖于AccountType和AccountStatus,但是这两个类都是抽象类,如果我们想再添加一个新的状态超支状态的话,不会对其他的类造成影响。

package com.designphilsophy.dip;

/**
 * 超支状态
 * @author xingjiarong
 *
 */
public class Overdrawn extends AccountStatus {
    public void sendCorrespondence() {
        // write your code here
    }
}

源码下载:http://download.csdn.net/detail/xingjiarong/9309387

  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
六大设计原则是指面向对象设计中的六个重要原则,它们是: 1. 单一职责原则(Single Responsibility Principle,SRP):一个类应该只有一个引起它变化的原因,即一个类应该只有一个职责。 2. 开放封闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。即在不修改已有代码的情况下,通过扩展来实现新的功能。 3. 里氏替换原则(Liskov Substitution Principle,LSP):子类型必须能够替换掉它们的父类型。即在使用基类对象的地方,可以用其子类对象来替代,而不会影响程序的正确性。 4. 接口隔离原则(Interface Segregation Principle,ISP):客户端不应该依赖它不需要的接口。即一个类对另一个类的依赖应该建立在最小的接口上。 5. 依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖低层模块,二者都应该依赖于抽象。即要针对接口编程,而不是针对实现编程。 6. 迪米特法则(Law of Demeter,LoD):一个对象应该对其他对象有尽可能少的了解,即一个对象应该只与其直接的朋友通信,而不与陌生的对象通信。 依赖倒置原则是六大设计原则中的一项,它强调高层模块不应该依赖低层模块,二者都应该依赖于抽象。具体来说,依赖倒置原则要求: 1. 高层模块不应该直接依赖于低层模块的具体实现,而应该依赖于抽象接口。 2. 抽象接口应该由高层模块定义,低层模块去实现。 3. 通过依赖倒置,可以降低模块间的耦合度,提高代码的可维护性和可扩展性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值