设计模式笔记(三)设计六大原则之三--依赖倒置原则

Dependence Inversion Principle, DIP

定义

1.高层模块不应该依赖底层模块,两者都应该依赖其抽象
2.抽象不应该依赖细节
3.细节应该依赖抽象
即:
1.模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
2.接口或抽象类不依赖于实现类
3.实现类依赖接口或抽象类

优点

1.减少类间的耦合性,提高系统稳定性
举个栗子:

/*
 * 司机
 */
public class Driver {
    //司机的主要职责就是驾驶汽车
    public void drive(Benz benz) {
        benz.run();
    }
}
/*
 * 奔驰汽车
 */
public class Benz {
    //汽车肯定会跑
    public void run() {
        System.out.println("奔驰汽车开始运行...");
    }
}
/*
 * 司机开车场景模拟
 */
public class Client {
    public static void main(String[] args) {
        Driver zhangSan = new Driver();
        Benz benz = new Benz();
        //张三开奔驰车
        zhangSan.drive(benz);
    }
}

现在司机不仅要开奔驰车,还要开宝马车:

/*
 * 宝马车
 */
public class BMW {
    //宝马车开动
    public void run() {
        System.out.println("宝马汽车开始运行...");
    }
}

但是我们现在发现,司机并不能开宝马车。这显然不合理,原因就是司机类和奔驰类是紧耦合的关系,这样一旦有新的车,比如宝马车来了,司机类就需要改动它的类代码,维护性大大降低,不稳定。

2.降低并行开发引起的风险,提高代码的可读性和可维护性。
现在开发的时候人员都是协作开发,可能每个人负责一个模块,也可能每个人负责一个类的编写或方法的编写。假如现在司机类由A来编写,奔驰车类由B来编写,很显然,在B编写完之前,A是不能开发成功的,为什么呢?编译器就不通过了,只能B开发完奔驰车类再由A来开发司机类,这样显然不利于项目进度,所以要解决模块之间的依赖关系。

按照依赖倒置原则,我们所有的高层模块都应该依赖于接口或抽象类。

/*
 * 司机接口
 */
public interface IDriver {
    //司机会驾驶汽车
    public void drive(ICar car);
}
/*
 * 司机
 */
public class Driver implements IDriver{
    //司机的主要职责就是驾驶汽车
//  public void drive(Benz benz) {
//      benz.run();
//  }

    @Override
    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 BMW implements ICar {
    //宝马车开动
    public void run() {
        System.out.println("宝马汽车开始运行...");
    }
}
/*
 * 司机开车场景模拟
 */
public class Client {
    public static void main(String[] args) {
        Driver zhangSan = new Driver();
        Benz benz = new Benz();
        //张三开奔驰车
        zhangSan.drive(benz);

        //张三开宝马车
        zhangSan.drive(new BMW());
    }
}

这时我们要让司机开宝马车只需要实现汽车接口即可,司机类不需要改动任何代码,即接口或抽象类(IDriver)并不依赖于汽车时哪一种的(细节)。

依赖的三种写法

这里的原理是依赖是可以传递的,只要做到抽象依赖,那么多层的传递也是正确的。

构造函数注入

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

public class Driver implements IDriver{
    private ICar car;

    //构造函数注入
    public Driver(ICar _car) {
        this.car = _car;
    }

    //司机的主要职责就是驾驶汽车
    public void drive() {
        this.car.run();
    }
}

setter依赖注入

/*
 * 司机接口
 */
public interface IDriver {
    //车辆型号
    public void setCar(ICar car);
    //司机会驾驶汽车
    public void drive(ICar car);
}

public class Driver implements IDriver{

    private ICar car;

    //构造函数注入
    public void setCar(ICar _car) {
        this.car = _car;
    }

    //司机的主要职责就是驾驶汽车
    public void drive() {
        this.car.run();
    }
}

接口声明依赖对象

/*
 * 司机接口
 */
public interface IDriver {
    //车辆型号
    public void setCar(ICar car);
    //司机会驾驶汽车
    public void drive(ICar car);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值