JAVA设原则之依赖倒置原则

本文介绍了依赖倒置原则的基本概念及应用案例,通过对比不同设计模式下的代码实现,阐述了依赖倒置原则如何降低模块间的耦合度,提高系统的可扩展性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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模式了~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值