依赖倒转原则 (Dependence Inversion Principle)

依赖倒转原则 (Dependence Inversion Principle)

定义:程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
  • 问题:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险

  • 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

  • 例子:CourseInfo 类调用 English 类和 Chinese 类 获取学科信息,今后如果增加其它学科,就需要修改 CourseInfo 类,这样违反类DIP,高层策略没有和低层实现分离,抽象没有和具体细节分离,没有这种分离,高层策略就自动地依赖于低层策略,抽象就自动地依赖于具体细节。

/**
 * 英语课程
 */
public class English {
    public static final String NAME = "英语";

    public void getClassTimeRange() {
        System.out.println("早上:8:00 - 10:00");
    }

    public void getContent() {
        System.out.println("学习英语语法");
    }
}
/**
 * 语文课程
 */
public class Chinese {
    public static final String NAME = "语文";

    public void getClassTimeRange() {
        System.out.println("早上:10:00 - 12:00");
    }

    public void getContent() {
        System.out.println("学习唐诗三百首");
    }
}
/**
 * 课程信息
 */
public class CourseInfo {
    private English english = new English();
    private Chinese chinese = new Chinese();

    public void getCourseInfo(String courseName) {
        if (English.NAME.equals(courseName)) {
            english.getClassTimeRange();
            english.getContent();
        } else if (Chinese.NAME.equals(courseName)) {
            chinese.getClassTimeRange();
            chinese.getContent();
        }
    }
}
  • 正确做法: 抽象出 ICourse 接口,English 类、Chinese 类、Math 类都继承该接口,而 CourseInfo 使用了 ICourse ,不管今后增加多学学科都无需修改 CourseInfo,并对于具体的实现类我们是不管的,只要接口的行为不发生变化,增加新的用户等级后,上层服务不用做任何的修改。这样设计降低了层与层之间的耦合,能很好地适应需求的变化,大大提高了代码的可维护性。
/**
 * 课程接口
 */
public interface ICourse {
    void getClassTimeRange();

    void getContent();
}
/**
 * 英语课程
 */
public class English implements ICourse{
    @Override
    public void getClassTimeRange() {
        System.out.println("早上:8:00 - 10:00");
    }

    @Override
    public void getContent() {
        System.out.println("学习英语语法");
    }
}
/**
 * 语文课程
 */
public class Chinese implements ICourse{
    @Override
    public void getClassTimeRange() {
        System.out.println("早上:10:00 - 12:00");
    }

    @Override
    public void getContent() {
        System.out.println("学习唐诗三百首");
    }
}
/**
 * 数学课程
 */
public class Math implements ICourse{
    @Override
    public void getClassTimeRange() {
        System.out.println("下午:02:00 - 04:00");
    }

    @Override
    public void getContent() {
        System.out.println("背乘法口诀");
    }
}
/**
 * 课程信息
 */
public class CourseInfo {
    public void getCourseInfo(ICourse iCourse) {
        iCourse.getClassTimeRange();
        iCourse.getContent();
    }
}
  • 总结:高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体,具体应该依赖于抽象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值