依赖倒置原则(Dependence Inversion Principle)

原始定义

       High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.


三层含义:

  1. 高层模块不应该依赖底层模块,两者都依赖其抽象。
  2. 抽象不依赖细节。
  3. 细节应该依赖于抽象。



【注解】在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的。细节就是具体的实现类,实现类实现了接口或继承了抽象类,其特点是可以直接被实例化。依赖倒置原则在Java语言中的表现是:

  • 模块间的依赖通过抽象产生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生。
  • 接口或抽象类不依赖于实现类,实现类依赖于接口或抽象类。

依赖倒置原则更加精确的定义就是“面向接口的编程”——OOD(Object-Oriented Design)的精髓之一。其是JavaBean、EJB和COM等组件设计模型背后的基本原则。


示例

       在现实生活中,司机只要会开车,就可以开奔驰车,也可以开宝马车。因此司机不依赖于奔驰或宝马车,而是通过如下图所示的接口,使他们之间的依赖关系倒置。


示例图片


       司机接口只是一个抽象的概念,是对司机这类事物的抽象,只要是司机都有一个共同的行为——开车,因此,在IDriver接口中使用drive()方法进行抽象。接口IDriver源代码如下:

public interface IDriver {
    //司机都会驾驶汽车
    public void drive(ICar car);
}



       司机类Driver实现IDriver接口,Driver源代码如下:

public class Driver implements IDriver {
    //司机的主要职责是驾驶
    @Override
    public void drive(ICar car) {
        car.run();
    }

}



       汽车接口ICar的源代码如下:

public interface ICar {
    //汽车都能跑
    public void run();
}



       奔驰汽车类Benz实现ICar接口,源代码如下:

public class Benz implements ICar {

    @Override
    public void run() {
        System.out.println("奔驰汽车在行使...");
    }

}



       宝马汽车类BMW也实现ICar接口,源代码如下:

public class BMW implements ICar {

    @Override
    public void run() {
        System.out.print("宝马汽车在行使...");
    }

}



       测试类Test,源代码如下:

public class Test {

    public static void main(String[] args) {
        //实例化一个司机
        IDriver tom = new Driver();
        //实例化一辆宝马车
        ICar car = new BMW();
        //tom开车
        tom.drive(car);
    }

}



【注解】这程序看起来就非常的6了,虽然规模很小,当司机tom想开奔驰车时,只需将“new BMW()”改为“new Benz()”即可,更改会引起的风险很小。这样的原则果然乃出自大牛之作,相比大家也迫不及待地想学习使用了,不过先别急,我们还需要弄懂一件事,那就是它适用的场景,有什么优点?
       依赖倒置原则在小型项目中很难体现出来。在大中型项目中,采用依赖倒置原则具有非常多的优点,特别是它能规避一些非技术原因引起的问题。项目越大,需求变化的概率也越大,采用依赖倒置原则可以使接口或抽象类对实现类进行约束,从而减少需求变化引起的工作量剧增的情况。人员的变动在大中型项目中也是时常存在的,如果程序设计优良、代码结构清晰时,人员变化对项目的影响就会很小。同时,它是实现开闭原则的重要途径,依赖倒置原则没有实现,就不能实现对扩展的开放,对修改关闭。
       在项目中使用这个原则需要遵循以下几个规则:

  • 每个类应该都具有接口或抽象类,或者同时具备抽象类和接口。
  • 变量的表面类型(表面类型是在定义的时候赋予的类型,实际类型是创建时对象的类型,例如tom表面类型是IDriver,实际类型是Driver)尽量是接口或者是抽象类。
  • 任何类都不应该从具体类派生。
  • 尽量不要重写基类的方法。如果基类是一个抽象类,并且其方法已经实现了,子类尽量不要重写。
  • 结合里氏替换原则。里氏替换原则指出父类出现的地方子类就可以出现,结合依赖倒置原则可以得出一个通俗的规则:接口负责定义抽象方法,并且声明与其他对象的依赖关系;抽象类负责公共构造部分的实现,实现类准确地实现业务逻辑,同时在适当的时候对父类进行细化。
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值