依赖倒置原则

一. 什么是依赖倒置原则
1.1 概念
依赖倒置原则(Dependence Inversion Principle, DIP), 其含义:

高层模块不应该依赖低层模块,两者都应该依赖其抽象
抽象不应该依赖细节, 细节应该依赖于抽象
要针对接口编程,不要针对实现编程
1.2 什么是依赖呢?
这里的依赖关系我们理解为UML关系中的依赖。简单的说就是A use B,那么A对B产生了依赖。具体请看下面的例子。

从上图中我们可以发现, 类A中的方法a()里面用到了类B, 其实这就是依赖关系, A依赖了B. 需要注意的是: 并不是说A中声明了B就叫依赖, 如果引用了但是没有真实调用方法, 那么叫做零耦合关系. 如下图:

1.3 依赖的关系种类

  1. 零耦合关系:如果两个类之间没有耦合关系,称之为零耦合

  2. 直接耦合关系: 具体耦合发生在两个具体类(可实例化的)之间,经由一个类对另一个类的直接引用造成。

  3. 抽象耦合关系: 抽象耦合关系发生在一个具体类和一个抽象类(或者java接口)之间,使两个必须***的类之间存在最大的灵活性。

依赖倒转原则就是要针对接口编程,不要针对实现编程。这就是说,应当使用接口或者抽象类进行变量的类型声明,参数的类型声明,方法的返回类型说明,以及数据类型的转换等。

二. 依赖倒置的案例
2.1 初步设计方案
public class Benz {
public void run() {
System.out.println(“奔驰跑起来了!”);
}
}

public class Driver {
private String name;
public Driver(String name) {
this.name = name;
}

public void driver(Benz benz) {
benz.run();
}
}

public class CarTest {
public static void main(String[] args) {
Benz benz = new Benz();
Driver driver = new Driver(“张三”);
driver.driver(benz);
}
}
有一个驾驶员张三可以驾驶奔驰 汽车 , 于是最开始我们思考, 会有一个驾驶员类, 有一个奔驰 汽车 类. 随着业务的发展, 我们发现, 驾驶员张三还可以驾驶 宝马 .

于是,我们定义一个BM类,

public class BM {
public void run() {
System.out.println(“宝马跑起来了!”);
}
}
这时, 张三如果想要开 宝马 , 就要将 宝马 注册在他名下.

public class Driver {
private String name;
public Driver(String name) {
this.name = name;
}

public void driver(Benz benz) {
benz.run();
}

public void driver(BM bm) {
bm.run();
}

}

public class CarTest {
public static void main(String[] args) {
Benz benz = new Benz();
BM bm = new BM();
Driver driver = new Driver(“张三”);
driver.driver(benz);
driver.driver(bm);
}
}
似乎这样就可以了, 但是这样有什么问题呢?

如果张三有一天要开大众, 还要增加一个大众车类, 同时还得挂载司机名下.
不是所有的人都要开奔驰, 开 宝马 . 开大众.
这就是面向实现编程的问题, 接下来我们就要考虑面向接口编程.

2.2 改进后的方案
public interface ICar {
public void run();
}

public class Benz implements ICar{
public void run() {
System.out.println(“奔驰跑起来了!”);
}
}

public class BM implements ICar{
public void run() {
System.out.println(“宝马跑起来了!”);
}
}

public interface IDriver {
public void driver(ICar car);
}

public class Driver implements IDriver{

public void driver(ICar car) {
car.run();
}
}

public class CarTest {
public static void main(String[] args) {
IDriver driver = new Driver();
driver.driver(new Benz());
driver.driver(new BM());
}
}
修改后的代码, 提炼出来一个IDriver接口和ICar接口, 面向接口编程. IDriver的实现类驾驶员可以driver任何类型的 汽车 , 所以传入参数也是一个接口ICar. 任何类型的 汽车 , 都可以通过实现ICar接口注册为一种新的 汽车 类型. 当 客户端 调用的时候, 将对应的 汽车 传入就可以了.

三. 依赖的方式
3.1 依赖注入主要有三种方式:
1 构造注入,在构造的时候注入依赖
Setter方法注入
接口方法中注入( 汽车 的例子使用的就是此方法)
3.2 依赖倒置原则在设计模式中的体现
简单工厂设计模式, 使用的是接口方法中注入
策略设计模式: 在构造函数中注入.
具体的用法, 可以查看以下两篇文章:
a. 简单工厂设计模式:
b. 策略设计模式:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淋风沐雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值