依赖倒置原则的定义百度搜一下,很绕口,在Java中的表现就是:
1.模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
2.接口或抽象类不依赖于实现类。
3.实现类依赖接口或抽象类。
它的本质用六个字概括就是“面向接口编程”。
我们先来看一下如果我们不是面向接口编程,我们会面临什么样子的窘境。
T先生最近写了一款软件赚了一大笔钱,于是他买了一辆宝马(BMW),那可是T先生的梦想,T先生曾经以为的business + money + woman.
于是他给自己写了一个程序。
public class BMW{
public void run() {
System.out.println("BMW is run");
}
}
public class Driver{
public void driver(BMW bmw) {
bmw.run();
}
}
public class Client {
public static void main(String[] args) {
Driver driver = new Driver();
BMW bmw = new BMW();
driver.driver(bmw);
}
}
代码很简单,我们来看一下他的类图。
但是昨天T先生有买了一辆奔驰S600,然后他看着自己写的程序,开始了他的烦恼。他发现他原来的类图的设计实在是太糟糕了,只加一辆车,就要改动所有类上的代码,因为这样的设计耦合性实在是太强了。那如果,以后再买辆保时捷,再买辆法拉利,这个时候T先生已经在眼冒金星了。
那我们来分析一下,这个案例虽然很简单,但是他折射出了我们在现实开发中的做法,在现实世界中,我们面向的都是实体,所以习惯告诉我们这样做法很符合我们的思维,也很好的适应了被需求压得喘不过气的我们。
然而,我们回过头来看,这完全没有体现TDD的设计思想,就是所谓的面向接口编程。下面我们来看一幅实现TDD设计的类图
具体代码就不实现了。看类图一目了然。
这样的设计,不论T先生将来买多少辆车,他都只需增加一个类就可以完成。
总结:现实开发中,我们怎么可以尽力满足这个原则呢?
1.每个类尽量都有接口或抽象类,或者抽象类和接口两者具备
2.变量的表面类型尽量是接口或者抽象类
3.任何类不应该从具体类派生
4.尽量不要覆写基类的方法
5.结合里氏替换原则使用