初探依赖倒置

1. 内容

『Dependence Inversion Principle』是 1996 年 Robert C.Martin 在 C++ Report 上发表的文章。

High level modules shouldnot depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions.
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。

要面向接口编程,不要面向实现编程。简单说即通过面向接口的编程来降低类间的耦合性

2. 作用

DIP 的主要作用:

  1. 降低类间的耦合性。
  2. 提高系统的稳定性。
  3. 减少并行开发引起的风险。
  4. 提高代码的可读性和可维护性。

3. 要点

3.1 依赖倒置与控制反转

控制反转和依赖倒置这两名词仅顾名思义的话,听起来还是『类似』的,其宗旨都是程序员要在环境或框架既定的规范下工作,而不得不丧失掉一部分代码的主动性

但是控制反转是 Spring 框架中的一个思想,即依赖方不需要关心被依赖对象的创建,只需要使用传进来的被依赖对象即可。

4. 场景

4.1 例一

商店类中有 sell() 方法,顾客类通过该方法购物以下代码定义了顾客类通过韶关网店 ShaoguanShop 购物:

1
2
3
4
5
6
class Customer {
public void shopping(ShaoguanShop shop) {
//购物
System.out.println(shop.sell());
}
}

如果该顾客想从另外一家商店(如婺源网店 WuyuanShop)购物,就要将该顾客的代码修改如下:

1
2
3
4
5
6
class Customer {
public void shopping(WuyuanShop shop) {
//购物
System.out.println(shop.sell());
}
}

顾客每更换一家商店,都要修改一次代码,这明显违背了开闭原则。解决方法是:定义婺源网店和韶关网店的共同接口 Shop,顾客类面向该接口编程,其代码修改如下:

1
2
3
4
5
6
class Customer {
public void shopping(Shop shop) {
//购物
System.out.println(shop.sell());
}
}

5. 最佳实践

  1. 每个类尽量提供接口抽象类,或者两者都具备。
  2. 变量的声明类型尽量是接口抽象类
  3. 大部分情况下类都不应该从具体类派生。
  4. 使用继承时尽量遵循里氏替换原则。

6. 系统优化

讨论