英文名称(Dependence Inversion Principle,DIP)
定义:高层模块不应该依赖低层模块,应该依赖其抽象,抽象不应该依赖其细节,细节应该依赖其抽象。
这句话在java中的理解:
低层模块:具体细化的java类
高层模块:是由多个低层模块组成的。
抽象:指的是接口或者抽象类
依赖:存在类A的一个方法S,S传入的参数是另一个类B的实例,那么类A依赖于类B我的理解---在项目开发中尽量将相同模块细化,类与类之间减少依赖关系,应该依赖其抽象类或者接口。
一个反面的例子:
----一个司机开宝马车。
按照常规的思维:定义一个司机类(Driver)有个void drive(BMW bmw)方法。该方法需要传入宝马车实例,
定义一个宝马车类(BMW) 有一个run方法。
public class DIPTest { public static void main(String[] args) { new Driver().drive(new BMW()); } } class Driver{ public void drive(BMW bmw){ System.out.println("司机开车..."); bmw.run(); } } class BMW{ public void run(){ System.out.println("宝马车开动了...."); } }更改需求,司机现在改开奔驰了,那么如果在这个类的基础上更改,我们需要给司机提供一个drive(Benz b)的方法。
同时再提供一个Benz类,提供一个run方法。那么就存在类之间的依赖性太大,不利于类的拓展。
----解决方案:
让细节类依赖其抽象,宝马车、奔驰车都具有run()方法,司机都具有drive(Car car)的方法。可以将共同的方法和类抽象成接口。
这样设计的好处,可以将司机和车分为两个模块进行开发,两者之间的依赖关系存在于接口,而具体实现类依赖于接口。这样在分工协作时,
只需要各自定义好接口的操作方法就可以了。并且类的扩展性也大大提高。
package hpu.lzl.dip; public class DIPTest2 { public static void main(String[] args) { IDriver d = new Driver2(); ICar ic = new BenzCar(); d.Driver(ic); System.out.println("----------------"); d.Driver(new BMWCar()); } } interface IDriver{ public void Driver(ICar car); } interface ICar{ public void run(); } class Driver2 implements IDriver{ @Override public void Driver(ICar car) { System.out.println("司机开车....."); car.run(); } } class BMWCar implements ICar{ @Override public void run() { System.out.println("宝马车开动了...."); } } class BenzCar implements ICar{ @Override public void run() { System.out.println("奔驰车开动了...."); } }依赖的三种写法
1、构造函数传递依赖
interface IDriver{ public void drive(); } class Driver2 implements IDriver{ private ICar car; public Driver2(ICar car){ this.car = car; } @Override public void drive() { System.out.println("司机发动车了..."); car.run(); } }
2、setter方法传递依赖
interface IDriver{ public void drive(); public void setCar(ICar car); } class Driver2 implements IDriver{ private ICar car; @Override public void drive() { System.out.println("司机开车....."); car.run(); } @Override public void setCar(ICar car) { // TODO Auto-generated method stub this.car = car; } }
3、接口传递依赖
interface IDriver{ public void drive(ICar car); } class Driver2 implements IDriver{ @Override public void drive(ICar car) { System.out.println("司机发动车了..."); car.run(); } }
我对依赖倒置的理解
依赖倒置首先要求类之间具有联系,将其联系抽象成接口或者抽象类,这样降低类之间的依赖。从而产生抽象类或接口之间的依赖,将具体事物时间的依赖转化成抽象接口的依赖。