JAVA设原则之依赖倒置原则
本博客大部分内容来自于网络,写下来方便以后查阅
1.什么是依赖倒置原则
简单来说
A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
B.抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
2.为什么要遵循依赖倒置原则
很多时候我们更改一个需求,发现更改一处地方需要更改多个文件,看见很多的报错我们自己都觉得烦,我们很清醒的意识到这是因为严重的耦合导致的,所以自然要想办法解决这个问题
3.依赖倒置有什么好处
简单来说,解决耦合。一般情况下抽象的变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。即使实现细节不断变动,只要抽象不变,客户程序就不需要变化。这大大降低了客户程序与实现细节的耦合度。
例子
公司是福特和本田公司的金牌合作伙伴,现要求开发一套自动驾驶系统,只要汽车上安装该系统就可以实现无人驾驶,该系统可以在福特和本田车上使用,只要这两个品牌的汽车使用该系统就能实现自动驾驶。
常规写法
既然是两种不同的汽车,那我们分别定义出来,一个Fute一个Bentian,代码如下:
public class Fute {
public void run() {
System.out.println("福特汽车启动");
}
public void stop() {
System.out.println("福特汽车停止");
}
}
public class Bentian{
public void run() {
System.out.println("本田汽车启动");
}
public void stop() {
System.out.println("本田汽车停止");
}
}
public class AtuoRunSystem {
private String mType;
private Bentian bentian;
private Fute fute;
public AtuoRunSystem(String type){
mType = type ;
bentian = new Bentian();
fute = new Fute();
}
public void AutoRun(){
if ("bentian".equals(mType)) {
bentian.run();
}else {
fute.run();
}
}
public void AutoStop(){
if ("bentian".equals(mType)) {
bentian.stop();
}else {
fute.stop();
}
}
}
代码很简单,相信有java基础的人一看就懂了,但是缺点也很明显,扩展性特别差,现在只有两种车,if-else语句还算简单,假设以后有100种车呢?是不是要改很多文件,写很多的if-else语句,这样岂不是把人忙死,效率很低。
那么,接下来我们开始改造。
首先观察福特和本田两个类
完全一模一样的代码是不是,那么我们开始抽离,写个抽象类或者接口都可以,这里我们写一个接口,有人纳闷为啥不写抽象类呢?根据我的个人见解,抽象类的抽象方法可以自己实现,但是接口的方法都是由子类实现的,车的功能我们具体细节我们不知道,没必要写出它的实现,所以,我们由子类实现,代码如下
public interface Icar {
void run();
void stop();
}
其次来我们看定义
A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
B.抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
在上述代码中,我们的AutoRunSystem类严重依赖于具体的子类,比如福特,本田,依赖了低层模块,而定义里已经说明,我们应该依赖于抽象,于是我们改造AutoRunSystem代码
代码如下:
public class AtuoRunSystem {
private Icar icar;
public AtuoRunSystem(Icar icar){
this.icar = icar;
}
public void autoRun(){
icar.run();
}
public void autoStop(){
icar.stop();
}
}
这样我们依赖的就是它的抽象类Icar。
public class Bentian implements Icar{
@Override
public void run() {
System.out.println("本田汽车启动");
}
@Override
public void stop() {
System.out.println("本田汽车停止");
}
}
public class Fute implements Icar{
public void run() {
System.out.println("福特汽车启动");
}
public void stop() {
System.out.println("福特汽车停止");
}
}
这样,我们就抽出了它的共同点。正好也呼应了B点,具体应该依赖于抽象,而不是抽象依赖于具体
这样,在main函数中,我们就可以这么使用了
public class Main {
public static void main(String[] args) {
AtuoRunSystem system = new AtuoRunSystem(new Bentian());
system.autoRun();
AtuoRunSystem system2 = new AtuoRunSystem(new Fute());
system2.autoRun();
}
}
是不是一下子明了多了,而且无论多少量车,我们都不用特别大改,只需要改一下抽象接口,写出它的具体实现,我们其他就不用管了,是不是很棒。
看懂这个,我们以后就可以看MVP模式了~~