## 英文名称(Dependence Inversion Principle ,DIP)
**定义**:高层模块不应该依赖低层模块,应该依赖其抽象,抽象不应该依赖其细节,细节应该依赖其抽象。
**这句话在java中的理解**:
低层模块:具体细化的java类
高层模块:是由多个低层模块组成的。
抽象:指的是接口或者抽象类
依赖:存在类A的一个方法S,S传入的参数是另一个类B的实例,那么类A依赖于类B 我的理解---在项目开发中尽量将相同模块细化,类与类之间减少依赖关系,应该依赖其抽象类或者接口。
一个反面的例子:
----一个司机开宝马车。
按照常规的思维:定义一个司机类(Driver)有个void drive(BMW bmw)方法。该方法需要传入宝马车实例,
定义一个宝马车类(BMW) 有一个run方法。
![](https://box.kancloud.cn/2016-06-06_57553406bfba4.jpg)
~~~
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)的方法。可以将共同的方法和类抽象成接口。
这样设计的好处,可以将司机和车分为两个模块进行开发,两者之间的依赖关系存在于接口,而具体实现类依赖于接口。这样在分工协作时,只需要各自定义好接口的操作方法就可以了。并且类的扩展性也大大提高。
![](https://box.kancloud.cn/2016-06-06_57553406dcb84.jpg)
~~~
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();
}
}
~~~
**我对依赖倒置的理解**
依赖倒置首先要求类之间具有联系,将其联系抽象成接口或者抽象类,这样降低类之间的依赖。从而产生抽象类或接口之间的依赖,将具体事物时间的依赖转化成抽象接口的依赖。
- 前言
- 6大设计原则(一)---单一职责原则
- 6大设计原则(二)---里氏替换原则
- 6大设计原则(三)---依赖倒置原则
- 6大设计模式(四)----接口隔离原则
- 6大设计原则(五)---迪米特法则
- 6大设计原则(六)---开闭原则。
- 设计模式(一)---单例模式
- 设计模式(二)---工厂方法模式
- 设计模式(三)---抽象工厂模式
- 设计模式(四)---模板方法模式
- 设计模式(五)---建造者模式
- 设计模式(六)---代理模式
- 设计模式(七)---原型模式
- 设计模式(八)---中介者模式
- 设计模式(九)---命令模式
- 设计模式(十)---责任链模式
- 设计模式(十一)---装饰模式
- 设计模式(十二)---策略模式
- 设计模式(十三)---适配器模式
- 设计模式(十四)---迭代器模式
- 设计模式(十五)---组合模式
- 设计模式(十六)---观察者模式
- 设计模式(十七)---门面模式
- 设计模式(十八)---备忘录模式
- 设计模式(十八)---访问者模式
- 设计模式(二十)---状态模式
- 设计模式(二十二)---享元模式
- 设计模式(二十三)---桥梁模式