1、依赖倒置原则
依赖倒置原则(Dependence Inversion Principle),简称DIP。首先来看看英文的定义吧,如下一长段:
High level modules should depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.
翻译过来,主要是三个意思:
1、高层模块不应该依赖低层模块,两者都应该依赖于抽象(抽象类或接口)
2、抽象(抽象类或接口)不应该依赖于细节(具体实现类)
3、细节(具体实现类)应该依赖抽象
2、实现方式
依赖倒置原则的本质骑士就是通过抽象(抽象类或接口)使各个类或模块的实现彼此独立,不相互影响,实现模块间的松耦合。但是这个原则也是6个设计原则中最难以实现的了,如果没有实现这个原则,那么也就意味着开闭原则(对扩展开发,对修改关闭)也无法实现。
依赖倒置的实现,主要有如下三种方法:
1、通过构造函数传递依赖对象,比如在构造函数中的需要传递的参数是抽象类或接口的方式实现;
2、通过setter方法传递依赖对象,即在我们设置的setXXX方法中的参数为抽象类或接口,来实现传递依赖对象;
3、接口声明实现依赖对象,我们接下来就要讲讲如何通过接口来实现依赖倒置,这也是依赖倒置最重要的实现手段。
3、传统方式
在传统中,我们可能会这样设计一个类,比如说,贾宝玉时一个富家公子,他只会做面条,一个人在家的时候只能吃自己做的面条。我们先看看吃面条这个类,如下:
/**
* 吃面条
* @author ljtyzhr
*
*/
public class Noodles {
public void eat(){
System.out.println("宝玉吃面条...");
}
}
接下来,我们看看,宝玉如何吃面条,如下:
/**
* 宝玉
* @author ljtyzhr
*
*/
public class Baoyu {
//宝玉是一个富家子弟,只会做面条
public void cook(Noodles noodles) {
noodles.eat();
}
}
如上所示,宝玉有一个对面条的引用,然后调用了面条吃的方法。
4、依赖倒置
如3中的解释说明,我们仅仅只能实现宝玉会做面条给自己吃。我们知道,后来宝玉出家了,他学会了做鱼,做饭,这个时候怎么办呢?扩展起来会很麻烦,那么我们事先能不能先定义一个食物类作为接口呢,等到学会什么,我们就添加什么?答案是可以的,这就是依赖倒置了。
我们先看看食物类的接口,以及两个实现类,一个是鱼,一个是米饭,如下:
public interface IFood {
public void eat();
}
public class Rice implements IFood {
@Override
public void eat() {
System.out.println("宝玉会煮饭了...");
}
}
public class Fishs implements IFood {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("额,当了和尚,会做也不能吃鱼");
}
}
再来看看一个测试类,如下:
/**
* 在家的场景
* @author ljtyzhr
*
*/
public class Home {
public static void main(String args[]){
Baoyu baoyu = new Baoyu();
IFood rice = new Rice();
baoyu.cook(rice);
IFood fish = new Fishs();
baoyu.cook(fish);
}
}
5、结果分析
宝玉会煮饭了...
额,当了和尚,会做也不能吃鱼