• 【云原生】一篇打通架构设计,Java设计模式6,依赖倒置原则


    在这里插入图片描述

    一、依赖倒置原则定义

    依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合

    面向过程的开发,上层调用下层,上层依赖于下层,当下层剧烈变动时上层也要跟着变动,这就会导致模块的复用性降低而且大大提高了开发的成本。

    面向对象的开发很好的解决了这个问题,一般情况下抽象的变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。即使实现细节不断变动,只要抽象不变,客户程序就不需要变化。这大大降低了客户程序与实现细节的耦合度。

    二、违背原则方案

    通过模拟项目经理获取工作进度的例子来说明依赖倒置原则。

    类中通过Stream对代码进行了简化,我觉得Stream是java8新特性中最好用,也是最简洁的,有兴趣的可以体验一下【Java8 新特性 5】Java 8 stream的详细用法

    1、项目经理

    package com.guor.beanutil.principle.inversion;
    
    import com.guor.beanutil.principle.dimit.Programmer;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ProjectManager {
        // 姓名
        private String name;
        // 项目
        private String project;
        // 进度
        private String schedule;
        // 计划完成时间
        private String completePlanTime;
        // 项目开发人员
        private static List<Programmer> programmerList;
    
        static {
            programmerList = new ArrayList<>();
            programmerList.add(new Programmer("哪吒","哪吒闹海","技术选型,框架搭建",0.5,Programmer.getDate("2022-08-20")));
            programmerList.add(new Programmer("妲己","哪吒闹海","前端",0.3,Programmer.getDate("2022-08-25")));
            programmerList.add(new Programmer("敖丙","哪吒闹海","权限项目",0.2,Programmer.getDate("2022-08-31")));
            programmerList.add(new Programmer("申公豹","哪吒闹海","管理模块",0.2,Programmer.getDate("2022-08-31")));
            programmerList.add(new Programmer("二郎神","哪吒闹海","数据迁移",0.1,Programmer.getDate("2022-09-05")));
        }
    
        public static List<Programmer> getProgrammerList(){
            return programmerList;
        }
    
        public static void main(String[] args) {
            // 获取平均项目进度
            System.out.println(AvgSchedule.getSchedule());// 0.26
            // 获取最慢项目进度
            System.out.println(MinSchedule.getSchedule());// 0.1
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    2、获取平均项目进度

    package com.guor.beanutil.principle.inversion;
    
    import com.guor.beanutil.principle.dimit.Programmer;
    import com.guor.beanutil.principle.dimit.ProjectManager;
    
    public class AvgSchedule {
        /**
         * 获取平均项目进度
         */
        public static Double getSchedule(){
            return ProjectManager.getProgrammerList().stream().mapToDouble( Programmer::getSchedule ).average().orElse(0d);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3、获取最慢项目进度

    package com.guor.beanutil.principle.inversion;
    
    import com.guor.beanutil.principle.dimit.Programmer;
    import com.guor.beanutil.principle.dimit.ProjectManager;
    
    public class MinSchedule {
        /**
         * 获取最慢项目进度
         */
        public static Double getSchedule(){
            return ProjectManager.getProgrammerList().stream().mapToDouble( Programmer::getSchedule ).min().orElse(0d);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    从测试结果上看,程序没有问题,验证结果正常。
    但如果程序时一成不变的,可以不考虑扩展性和可维护性,那么这么做一点毛病没有。
    但是,如果程序具有很多的不确定性,或者当业务发生变化时,需要不断的调整和新增,那么这样的方式似乎不是很友好。
    首先,这样的方式扩展起来很麻烦,每次扩展都需要新增接口,同时对于调用方来说需要新增调用接口的代码。其次,对于这个服务类来说,随着接口数量的增加,代码行数会不断地暴增,最后难以维护。

    三、依赖倒置原则改善代码

    首先上述方式不具备良好的扩展性,那么用依赖倒置、面向抽象编程的方式实现就可以解决这个问题。

    首先定义获取项目进度的接口,任何一个实现类都可以实现自己的计算逻辑。

    1、获取项目进度接口

    package com.guor.beanutil.principle.inversion;
    
    /**
     * 获取项目进度
     */
    public interface IGetSchedule {
    
        Double getSchedule();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2、获取平均项目进度实现类

    package com.guor.beanutil.principle.inversion;
    
    import com.guor.beanutil.principle.dimit.Programmer;
    import com.guor.beanutil.principle.dimit.ProjectManager;
    
    public class AvgSchedule implements IGetSchedule {
    
        /**
         * 获取平均项目进度
         */
        @Override
        public Double getSchedule() {
            return ProjectManager.getProgrammerList().stream().mapToDouble( Programmer::getSchedule ).average().orElse(0d);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3、获取最慢项目进度实现类

    package com.guor.beanutil.principle.inversion;
    
    import com.guor.beanutil.principle.dimit.Programmer;
    import com.guor.beanutil.principle.dimit.ProjectManager;
    
    public class MinSchedule implements IGetSchedule {
    
        /**
         * 获取最慢项目进度
         */
        @Override
        public Double getSchedule() {
            return ProjectManager.getProgrammerList().stream().mapToDouble( Programmer::getSchedule ).min().orElse(0d);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    4、项目经理测试类

    package com.guor.beanutil.principle.inversion;
    
    import com.guor.beanutil.principle.dimit.Programmer;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ProjectManager {
        // 姓名
        private String name;
        // 项目
        private String project;
        // 进度
        private String schedule;
        // 计划完成时间
        private String completePlanTime;
        // 项目开发人员
        private static List<Programmer> programmerList;
    
        static {
            programmerList = new ArrayList<>();
            programmerList.add(new Programmer("哪吒","哪吒闹海","技术选型,框架搭建",0.5,Programmer.getDate("2022-08-20")));
            programmerList.add(new Programmer("妲己","哪吒闹海","前端",0.3,Programmer.getDate("2022-08-25")));
            programmerList.add(new Programmer("敖丙","哪吒闹海","权限项目",0.2,Programmer.getDate("2022-08-31")));
            programmerList.add(new Programmer("申公豹","哪吒闹海","管理模块",0.2,Programmer.getDate("2022-08-31")));
            programmerList.add(new Programmer("二郎神","哪吒闹海","数据迁移",0.1,Programmer.getDate("2022-09-05")));
        }
    
        public static List<Programmer> getProgrammerList(){
            return programmerList;
        }
    
        public static void main(String[] args) {
            ScheduleController scheduleController = new ScheduleController();
            // 获取平均项目进度
            Double schedule = scheduleController.getSchedule(new AvgSchedule());// 0.26
            System.out.println(schedule);
            // 获取最慢项目进度
            schedule = scheduleController.getSchedule(new MinSchedule());// 0.1
            System.out.println(schedule);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    5、控制台输出

    在这里插入图片描述
    这与前面代码唯一的不同是新增了实现获取项目进度的入参new AvgSchedule()new MinSchedule()
    在这两个计算方式作为入参后,扩展起来会非常的方便。

    以这种抽象接口为基准搭建起来的框架结构会更加稳定,扩展性更好,条理更加清晰。

    依赖倒置原则虽然看似简单,但如果想在实际项目开发中,将各模块、功能规划的井井有条,运用的炉火纯青、恰到好处,真的很难。反复阅读,仔细体会。

    四、无语!继Java之父,Java8再次被弃用。。。

    继Java 之父 James Gosling 先前称,开发者应尽快弃用 JDK 8,可以选择 JDK 17 LTS,因为后者在各个方面都带来了巨大的改进。
    在这里插入图片描述
    开源 Devops 工具 Jenkins 宣布:从 6 月 28 日发布的 Jenkins 2.357 和即将发布的 9 月 LTS 版本开始,Jenkins 最低需要 Java 11。
    在这里插入图片描述
    Jenkins 最初称为 Hudson ,是一款老牌持续集成工具,至今已创立十多年。自 2005 年成立以来,Jenkins 项目经历了多次 Java 迁移。目前从 Java 8 到 Java 11 的迁 移与 Jenkins 项目中的迁移历史是一致的。
    在这里插入图片描述
    开发者 Basil Crow 在博客中解释称:Jenkins 项目在短期内可能会保留在 Java 8 上,但出于几个原因,这样做是弊大于利。首先,Jenkins 项目使用的许多关键第三方库(例如,Jetty、JGit、Spring Framework 和 Spring Security)开始需要更新版本的 Java,而停留在 Java 8 上会使 Jenkins 项目无法从上游项目接收安全更新。
    此外,新版本 Java 对 Java 平台进行了显着的运行时改进。例如,LinkedIn 在迁移到 Java 11 时看到了显着的性能改进,而 Adoptium 在迁移到 Java 11 时看到了显着的内存使用改进(在 Jenkins 上同样如此),而最近的 Java 运行时则提供了许多对垃圾收集的改进。
    最后,保持 Java 的当前版本有助于 Jenkins 吸引和留住开发人员。
    目前,官方的 Jenkins Docker 镜像 已经基于 Java 11 好几个月了,Java 8 暂时还可作为备选,Java 17 可在预览模式下使用。但是从 Jenkins 2.357 开始,Java 8 映像就将被淘汰,Java 17 映像从预览版过渡到一般可用性 (GA)。

    事实上 Jenkins 团队更推荐用户使用 Java 17 :

    Jenkins 对 Java 17 的支持是全新的,不过它还没有达到在 Jenkins 社区内普遍采用的阶段。
    尽管如此, 我们的经验是 Java 17 是比 Java 11 更可靠的选择,我们可以自信地说,从 Java 11 迁移到 Java 17 不会像从 Java 8 迁移到 Java 11 那样痛苦。

    在这里插入图片描述

    《Java核心技术》第 12 版根据 最新的 LTR 版本 Java 17 全面更新,涵盖了 Java8-17 全部版本的特性,相应调整了部分内容结构,同时延续之前版本的优良传统,利用清晰明了的示例加以解释,并提供了全部示例代码,以便读者学习和灵活应用。它将续写从前的辉煌,使开发者能及时跟上 Java 前进的步伐。

    新书上市,在各大平台本书均有大力度的折扣,全网低价,还不快闭眼入手!

    文末送书:送5本《Java核心技术》第12版
    送书方式:查看👇🏻👇🏻👇🏻,回复9527,获取活动方式👇🏻👇🏻👇🏻,或私信哪吒参与

  • 相关阅读:
    【Leetcode】面试题 02.02. 返回倒数第 k 个节点
    linux的su:鉴定故障,或当密码正确
    windows安装jenkins2.346.1
    MySQL之体系架构
    Nuxt3 简单集成 GoogleMap
    LinkedList与链表
    万字长文详解对账系统设计,推荐收藏
    安装node.js后进行的操作(配置node环境变量、npm镜像加速、安装vue-cli项目脚手架、在IDEA中打开并运行脚手架)
    【付费推广】常见问题合集,搜索推广FAQ 2
    竞赛选题 深度学习的水果识别 opencv python
  • 原文地址:https://blog.csdn.net/guorui_java/article/details/126085276