6大设计原则之依赖倒置原则(Dependence Inversion Principle)。

来源:互联网 发布:农村创业软件 编辑:程序博客网 时间:2024/06/05 13:24

定义:

  • 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
  • 抽象不应该依赖细节;
  • 细节应该依赖抽象。
依赖倒置原则在Java语言中的表现就是:

  • 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
  • 接口或抽象类不依赖于实现类;
  • 实现类依赖接口或抽象类。
更加精简的定义就是“面向接口编程”——OOD(Object-Oriented Design,面向对象设计)的精髓之一。

采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。

注意:设计是否具备稳定性,只要适当地“松松土”,观察“设计的蓝图”是否还可以茁壮地成长就可以得出结论,稳定性较高的设计,在周围环境频繁变化的时候,依然可以做到“我自岿然不动”。


司机接口(接口只是一个抽象化的概念,是对一类事物的最抽象描述)

public interface IDriver {

  // 是司机就应该会驾驶汽车

  public void drive(ICar car);

}

司机类的实现

public class Driver implements IDriver {

  // 司机的主要职责就是驾驶汽车

  public void drive(ICar car) {

   car.run();

  }

}

汽车接口

public interface ICar {

  // 是汽车就应该能跑

  public void run();

}

奔驰汽车类(宝马汽车类似,故省略)

public class Benz implements ICar {

  // 汽车肯定会跑

  public void run() {

    System.out.println("奔驰汽车开始运行...");

  }

}

业务场景

public class Client {

  public static void main(String[] args) {

    IDriver zhangSan = new Driver();

    ICar benz = new Benz();

    // 张三开奔驰车

     zhangSan.drive(benz);

  }

}

注意:在Java中,只要定义变量就必然要有类型,一个变量可以有两种类型:表面类型和实际类型,表面类型是在定义的时候赋予的类型,实际类型是对象的类型,如zhangSan表面类型是IDriver,实际类型是Driver。

TDD(Test-Driven Development,测试驱动开发)就是依赖倒置原则的最高级应用。JMock工具,其最基本的功能是根据抽象虚拟一个对象进行测试。

测试类

public class DriverTest extends TestCase {

  Mockery context = new Junit4Mockery();

  @Test

  public void testDriver() {

    // 根据接口虚拟一个对象

    final ICar car = context.mock(ICar.class);

    IDriver driver = new Driver();

    // 内部类

    context.checking(new Exception(){{

        oneOf  (car).run();

    }});

    driver.drive(car);

  }

}

注意粗体部分,我们只需要一个ICar的接口,就可以对Driver类进行单元测试。从这一点来看,两个相互依赖的对象可以分别进行开发,孤立地进行单元测试,进而保证并行开发的效率和质量,TDD开发的精髓不就在这里吗?测试驱动开发,先写好单元测试类,然后再写实现类,这对提高代码的质量有非常大的帮助,特别适合研发类项目或在项目成员整体水平比较低的情况下采用。


对象的依赖关系有三种方式来传递:

  1. 构造函数传递依赖对象
  2. Setter方法传递依赖对象
  3. 接口声明依赖对象

最佳实践:
依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合。
  • 每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备;
  • 变量的表面类型尽量是接口或者是抽象类(比如工具类就一般不需要接口或者抽象类)。
  • 任何类都不应该从具体类派生
  • 尽量不要覆写基类的方法
  • 结合里氏替换原则使用

通俗的规则:接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当地时候对父类进行细化。

阅读全文
0 0
原创粉丝点击