依赖倒置原则——举例说明Java设计模式中的依赖倒置原则

2022/2/13 14:15:35

本文主要是介绍依赖倒置原则——举例说明Java设计模式中的依赖倒置原则,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

依赖倒置原则——举例说明Java设计模式中的依赖倒置原则

  • 一、前言
    • 看官方定义
  • 二、举例说明
    • 2.1 例子介绍(无聊的可看看,着急的请跳过)
    • 2.2 反例
      • 2.1.1 反例1
        • (1)类图说明
        • (2)代码说明
        • (3)测试
        • (4)分析优缺点
      • 2.1.2 反例2——反例1上维护
        • (1)类图说明
        • (2)代码说明
        • (3)测试
        • (4)分析优缺点
          • 1)优缺点分析
          • 2)如何解决?
    • 2.3 正例
      • 2.2.1 正例1
        • (1)类图说明
        • (2)代码说明
        • (3)测试
        • (4)分析优缺点
      • 2.2.2 正例2——正例1上维护
        • (1)类图说明
        • (2)代码说明
        • (3)测试
  • 三、总结
    • 3.1 倒置?为什么叫倒置?
    • 3.3 再琢磨一下官方概念
    • 3.4 作用
    • 3.5 使用原则
  • 四、附代码
    • 反例1
    • 反例2
    • 正例1
    • 正例2

一、前言

  • 依赖倒置原则也称依赖倒转原则(Dependence Inversion Principle)

看官方定义

  • 高层模块不应该依赖底层模块,二者都应该依赖其抽象

  • 抽象不应该依赖细节,细节应该依赖抽象

  • 依赖倒置的中心思想是面向接口编程

  • 如果你了解点设计模式,应该理解上面的话,但是如果不了解的话,感觉说的云里雾里的,是不是一脸懵,懵这就对了,那就先看例子吧,会帮助你理解的!

二、举例说明

2.1 例子介绍(无聊的可看看,着急的请跳过)

  • 能看下面的类图就看图,能看代码就看代码,我就是简单说一下例子的想法
  • 如果你问身边的人或者看网上的代码都不是自己的思想,如果你没有勇气把公司的代码都用设计模式优化一遍,那就忍着,等你的架构师忍不住的时候再动手,但是如果学完东西不实操很容易就忘记。
  • 那这就需要好的例子了,其实举例也是思想得一部分,懂得多了,就信手拈来,公司中好多人都会跟你说只可意会不可言传,我挺讨厌这句话的,说了等于没说,如果你不想继续当码农,不妨把生活应用于实践,别人问你什么你能用通俗易懂的例子告诉他,你就赢了!
  • 因为我养着一条狗叫麦兜,心里又喜欢着猫,想在多年后一定要养一只布偶或者德文,所以我的很多例子都是很麦兜有关系,设计来源于生活!那下面的例子就是家庭养殖场养殖各种宠物的例子

2.2 反例

2.1.1 反例1

(1)类图说明

  • 先介绍一下这几个类,待会看图理解
    FamilyFarm–>家庭养殖场类,不定时的收养宠物
    DogGrowthProcess–>狗狗成长过程类,记录狗狗从出生到被收养的过程
    ClientTest–>不说了,说多了都是废话,测试类
  • 通俗易懂,直接上图:
    在这里插入图片描述
  • 不是很明白的话,再往下看代码说明

(2)代码说明

在这里插入图片描述

(3)测试

在这里插入图片描述

(4)分析优缺点

  • 咋看,没毛病,通俗易懂;再看,不便于维护,屎代码,恶心难受
  • 我知道看完之后肯定觉得这段代码通俗易懂,简单的不能再简单了,而且你还会觉得,即便下次再收养个猫,复制剪贴加上就行了呀,也挺好维护的呀,真的吗?那问题是?请继续……

2.1.2 反例2——反例1上维护

(1)类图说明

在这里插入图片描述

(2)代码说明

在这里插入图片描述
在这里插入图片描述

(3)测试

在这里插入图片描述

(4)分析优缺点

1)优缺点分析
  • 这样增加新功能的时候看似简单,也确实不难,但是随着项目的扩大,尤其是实际开发的项目非常的庞大,像这样每增加一个新功能,每增加一个新类你都要改养殖场类 FamilyFarm(你可以这么理解,我就是一个养殖场,你有新品种了直接给我送来就行,我为啥还要各种修改呢,我不动不行吗?你不给我提供快捷方式,我不跟你合作了……)
  • FamilyFarm 是一个养殖场,可能养很多动物,具体养什么不知道,你可以把他理解抽象一点儿,而狗狗和小猫的成长过程都是具体的细节,所以 FamilyFarm 不应该依赖细节,否则就像上面代码一样后续维护困难,倒置养殖场不跟你合作了。
2)如何解决?
  • 怎么解决呢,这就需要我们的依赖倒置原则了:
    FamilyFarm 不是没有依赖抽象吗?那我们就引进抽象,不让他依赖具体细节,那抽象又是怎么,怎么设置呢?
    你想呀,FamilyFarm 不能依赖狗狗猫猫成长过程的那些细节了,所以抽象就是要把狗狗猫猫羊羊????????的成长细节抽象出来,说到这里明白了吧!
  • 好了,往下看例子,会更形象点,看完,我让你不想明白就难!
  • 写到这里,突然觉得不继续当老师真的浪费了,害,算了算了,清醒点,别自恋了,真的养不活自己和我的麦兜,还是默默地做个码农吧!

2.3 正例

2.2.1 正例1

(1)类图说明

  • 直接上图:
    在这里插入图片描述
  • 图说明了一切,以后再有新增动物,FamilyFarm 还会继续跟你合作,因为你让他省事到只写一次就为一生,太方便了!

(2)代码说明

在这里插入图片描述
在这里插入图片描述

(3)测试

在这里插入图片描述

(4)分析优缺点

  • 对比反例,代码的可读性明显提高,后续维护也好维护了

2.2.2 正例2——正例1上维护

  • 这个就不细说了,就是新增一个饲养羊的新功能,你感受一下即可

(1)类图说明

在这里插入图片描述

(2)代码说明

在这里插入图片描述

  • 这就完了,就问你妙不妙,接下来就是测试了!

(3)测试

在这里插入图片描述

三、总结

3.1 倒置?为什么叫倒置?

  • 看完上面案例,现在明白了吗?
  • 反例:家庭农场依赖狗狗猫猫的成长过程的细节
  • 正例:狗狗猫猫羊羊都继承了 petGrowthProcess 接口(即:让细节依赖抽象),家庭农场 依赖抽象,不再依赖细节;这不就倒回来了嘛

3.3 再琢磨一下官方概念

  • 琢磨概念之前先简单说一下Java基础:
    在Java中,抽象指的是接口或者抽象类,而具体的实现类指的是细节。
  • 依赖倒置基于细节应该依赖抽象等设计理念,相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的框架要稳定的多
  • 使用接口或抽象类的目的是指定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现去完成。
  • 即:依赖倒置的思想就是面向接口编程思想

3.4 作用

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

3.5 使用原则

  1. 底层模块,尽量都要有抽象类或者接口,或者两者都具备,这样程序的稳定性会更好;
  2. 变量的声明类型尽量是接口或者是抽象类。
  3. 使用继承时尽量遵循里氏替换原则。

四、附代码

反例1

package com.liu.susu.principle.inversion.example1;

/**
 * @FileName FamilyFarm
 * @Description
 * @Author susu
 * @date 2022-02-13
 **/
public class FamilyFarm {

    public void raiseDog(DogGrowthProcess dogGrowthProcess){
        dogGrowthProcess.dogBorn();
        dogGrowthProcess.dogGrowUp();
        dogGrowthProcess.dogBeRaised();
    }
}

class DogGrowthProcess {
    public void dogBorn(){
        System.out.println("狗狗-->麦兜出生了……");
    }
    public void dogGrowUp(){
        System.out.println("狗狗-->麦兜长大了……");
    }
    public void dogBeRaised(){
        System.out.println("狗狗-->麦兜被饲养员带走了……");
    }
}

class ClientTest{
    public static void main(String[] args) {
        //狗狗长大了,开始饲养狗狗
        new FamilyFarm().raiseDog(new DogGrowthProcess());
    }
}

反例2

package com.liu.susu.principle.inversion.example2;

/**
 * @FileName Breeder
 * @Description
 * @Author susu
 * @date 2022-02-13
 **/
public class FamilyFarm {

    public void raiseDog(DogGrowthProcess dogGrowthProcess){
        dogGrowthProcess.dogBorn();
        dogGrowthProcess.dogGrowUp();
        dogGrowthProcess.dogBeRaised();
    }

    public void raiseCat(CatGrowthProcess catGrowthProcess){
        catGrowthProcess.catBorn();
        catGrowthProcess.catGrowUp();
        catGrowthProcess.catBeRaised();
    }

}

class DogGrowthProcess {
    public void dogBorn(){
        System.out.println("狗狗-->麦兜出生了……");
    }
    public void dogGrowUp(){
        System.out.println("狗狗-->麦兜长大了……");
    }
    public void dogBeRaised(){
        System.out.println("狗狗-->麦兜被饲养员带走了……");
    }
}

class CatGrowthProcess {
    public void catBorn(){
        System.out.println("小猫-->阿苔出生了……");
    }
    public void catGrowUp(){
        System.out.println("小猫-->阿苔长大了……");
    }
    public void catBeRaised(){
        System.out.println("小猫-->阿苔被饲养员带走了……");
    }
}

class ClientTest{
    public static void main(String[] args) {
        //开始饲养狗狗
        new FamilyFarm().raiseDog(new DogGrowthProcess());
        //开始饲养小猫
        new FamilyFarm().raiseCat(new CatGrowthProcess());
    }
}

正例1

package com.liu.susu.principle.inversion.example3;

/**
 * @FileName FamilyFarm
 * @Description 使用 依赖倒置原则 优化后的代码
 * @Author susu
 * @date 2022-02-13
 **/
public class FamilyFarm {

    public void raisePet(petGrowthProcess petGrowthProcess){
        petGrowthProcess.petBorn();
        petGrowthProcess.petGrowUp();
        petGrowthProcess.petBeRaised();
    }

}
interface petGrowthProcess{
    void petBorn();
    void petGrowUp();
    void petBeRaised();
}
class DogGrowthProcess implements petGrowthProcess{
    public void petBorn(){
        System.out.println("狗狗-->麦兜出生了……");
    }
    public void petGrowUp(){
        System.out.println("狗狗-->麦兜长大了……");
    }
    public void petBeRaised(){
        System.out.println("狗狗-->麦兜被饲养员带走了……");
    }
}

class CatGrowthProcess implements petGrowthProcess{
    public void petBorn(){
        System.out.println("小猫-->阿苔出生了……");
    }
    public void petGrowUp(){
        System.out.println("小猫-->阿苔长大了……");
    }
    public void petBeRaised(){
        System.out.println("小猫-->阿苔被饲养员带走了……");
    }
}

class ClientTest{
    public static void main(String[] args) {
        FamilyFarm familyFarm = new FamilyFarm();
        //饲养狗狗
        familyFarm.raisePet(new DogGrowthProcess());
        //饲养小猫
        familyFarm.raisePet(new CatGrowthProcess());
    }
}

正例2

package com.liu.susu.principle.inversion.example4;

/**
 * @FileName FamilyFarm
 * @Description 使用 依赖倒置原则 优化后的代码
 * @Author susu
 * @date 2022-02-13
 **/
public class FamilyFarm {

    public void raisePet(petGrowthProcess petGrowthProcess){
        petGrowthProcess.petBorn();
        petGrowthProcess.petGrowUp();
        petGrowthProcess.petBeRaised();
    }

}

interface petGrowthProcess{
    void petBorn();
    void petGrowUp();
    void petBeRaised();
}

class DogGrowthProcess implements petGrowthProcess{
    public void petBorn(){
        System.out.println("狗狗-->麦兜出生了……");
    }
    public void petGrowUp(){
        System.out.println("狗狗-->麦兜长大了……");
    }
    public void petBeRaised(){
        System.out.println("狗狗-->麦兜被饲养员带走了……");
    }
}

class CatGrowthProcess implements petGrowthProcess{
    public void petBorn(){
        System.out.println("小猫-->阿苔出生了……");
    }
    public void petGrowUp(){
        System.out.println("小猫-->阿苔长大了……");
    }
    public void petBeRaised(){
        System.out.println("小猫-->阿苔被饲养员带走了……");
    }
}

//新增功能饲养羊
class sheepGrowthProcess implements petGrowthProcess{
    public void petBorn(){
        System.out.println("小羊-->点点出生了……");
    }
    public void petGrowUp(){
        System.out.println("小羊-->点点长大了……");
    }
    public void petBeRaised(){
        System.out.println("小羊-->点点被饲养员带走了……");
    }
}

class ClientTest{
    public static void main(String[] args) {
        FamilyFarm familyFarm = new FamilyFarm();
        //饲养狗狗
        familyFarm.raisePet(new DogGrowthProcess());
        //饲养小猫
        familyFarm.raisePet(new CatGrowthProcess());
        //新增功能饲养羊
        familyFarm.raisePet(new sheepGrowthProcess());
    }
}


这篇关于依赖倒置原则——举例说明Java设计模式中的依赖倒置原则的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程