Java使用策略模式和工厂模式来消除冗余的if-else语句(UML类图+案例+提供Gitee源码)

news2024/12/28 21:04:11

前言:在最近的后端开发中,多多少少会发现有很多if-else语句,如果条件过多则会造成整体代码看起来非常臃肿,这边我就举一个我在实际开发中的例子,来进行阐述这两种模式在实际开发中我是如何运用的。

目录

一、工厂模式简介

二、简单工厂模式

2.1、UML类图

2.2、角色设计

2.3、代码实现

2.4、总结

三、工厂方法模式

3.1、UML类图

3.2、角色设计 

3.2、代码实现

3.3、总结

四、抽象工厂模式

4.1、UML类图

4.2、角色设计 

4.3、代码实现

4.4、总结

五、策略模式

5.1、UML类图

5.2、角色设计

5.3、代码实现

5.4、总结

六、使用工厂模式+策略模式消除冗余if-else语句

七、Gitee源码


一、工厂模式简介

工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,具体可以分为三种来进行逐一介绍,分别是简单工厂模式、工厂方法模式以及抽象工厂模式。这种模式可以使得我们代码的整体结构更加信息,有效的动态进行封装以及降低代码之间的耦合度。

二、简单工厂模式

2.1、UML类图

2.2、角色设计

角色描述
简单工厂负责创建所有实体类的内部逻辑,工厂类创建产品的方法可以直接被外部调用,以此来创建所修要的产品对象
抽象水果简单工厂模式创建对象的公用接口
具体水果公用接口创建的具体对象

2.3、代码实现

1、自定义一个水果接口

public interface Fruit {

    public void name();

}

2、自定义水果类-苹果

public class Apple implements Fruit{

    @Override
    public void name() {
        System.out.println("苹果");
    }

}

3、自定义水果类-西瓜

public class Watermelon implements Fruit{

    @Override
    public void name() {
        System.out.println("西瓜");
    }

}

4、创建一个简单的水果工厂,通过传递进来的水果名词进行生产水果

public class FruitFactory {

    public static Fruit makeFruit(String name){
        if("苹果".equals(name)){
            return new Apple();
        }else if ("西瓜".equals(name)){
            return new Watermelon();
        }else {
            return null;
        }
    }
    
}

5、市场类

public class Market {
    public static void main(String[] args) {
        Fruit fruit = FruitFactory.makeFruit("西瓜");
        fruit.name();
    }
}

2.4、总结

优点:简单工厂模式封装了创建对象的逻辑,完成了创建对象逻辑和业务代码之间的解耦。

缺点:每个具体的水果类的接口增多时,会需要在简单工程类中新增大批的对象生产的方法,这样在抽象工厂当中会有很多的if-else语句,同时也违背了“对修改关闭,对扩展开启的”原则(开闭原则)

三、工厂方法模式

3.1、UML类图

3.2、角色设计 

角色描述
抽象水果工厂定义了创建水果的方法,任何模式中在创建水果的工厂类必须实现这个接口
具体水果工厂实现抽象水果工厂接口的具体水果工厂类,负责生产具体的水果产品
抽象水果水果对象公用的接口
具体水果实现了抽象水果定义的接口,某具体的水果由某具体的工厂进行创建

3.2、代码实现

1、定义水果工厂接口

public interface FruitFactory {

    Fruit makeFruit();
    
}

2、定义水果接口

public interface Fruit {

    public void name();
    
}

3、自定义苹果实现类

public class Apple implements Fruit{

    @Override
    public void name() {
        System.out.println("苹果");
    }

}

4、自定义西瓜实现类

public class Watermelon implements Fruit{

    @Override
    public void name() {
        System.out.println("西瓜");
    }
    
}

5、自定义苹果生产工厂

public class AppleFactory implements FruitFactory{

    @Override
    public Fruit makeFruit() {
        return new Apple();
    }
    
}

6、自定义西瓜生产工厂

public class WatermelonFactory implements FruitFactory{

    @Override
    public Fruit makeFruit() {
        return new Watermelon();
    }

}

7、市场类

public class Market {
    
    public static void main(String[] args) {
        AppleFactory appleFactory = new AppleFactory();
        appleFactory.makeFruit().name();
    }
    
}

3.3、总结

优点:在简单工厂模式的基础上进行优化,完美符合了“开闭原则”和“单一职责原则”,便于进行扩展。

缺点:类的个数容易过多,增加代码的复杂度并且抽象工厂接口的具体工厂只可以生产单独一个类型的产品。

四、抽象工厂模式

4.1、UML类图

4.2、角色设计 

角色描述
抽象工厂声明生产水果的一个工厂接口(可以声明生产多个类型产品的方法)
具体工厂实现生产水果的具体实体类
抽象水果水果对象公用的接口
具体水果实现了抽象水果定义的接口,某具体的水果由某具体的工厂进行创建

4.3、代码实现

1、定义水果工厂接口

public interface FruitFactory {

    Fruit makeFruit();

    Package makePackage();

}

2、定义水果接口

public interface Fruit {

    public void name();

}

3、 定义苹果实现类以及对应的苹果包装实现类

public class Apple implements Fruit {

    @Override
    public void name() {
        System.out.println("苹果");
    }

}

public class ApplePackage implements Package{
    
    @Override
    public void name() {
        System.out.println("苹果包装");
    }
    
}

4、 定义西瓜实现类以及对应的西瓜包装实现类

public class Watermelon implements Fruit {

    @Override
    public void name() {
        System.out.println("西瓜");
    }

}

public class WatermelonPackage implements Package{

    @Override
    public void name() {
        System.out.println("西瓜包装");
    }
    
}

5、 自定义苹果工厂

public class AppleFactory implements FruitFactory {

    @Override
    public Fruit makeFruit() {
        return new Apple();
    }

    @Override
    public Package makePackage() {
        return new ApplePackage();
    }

}

6、自定义西瓜工厂

public class WatermelonPackage implements Package{

    @Override
    public void name() {
        System.out.println("西瓜包装");
    }
    
}

7、市场类

public class Market {

    public static void main(String[] args) {
        FruitFactory appleFactory = new AppleFactory();
        FruitFactory watermelonFactory = new WatermelonFactory();

        appleFactory.makeFruit().name();
        appleFactory.makePackage().name();

        watermelonFactory.makeFruit().name();
        watermelonFactory.makePackage().name();
    }

}

4.4、总结

优点:抽象工厂模式在工厂方法模式进行了进一步延伸,都是符合“开闭原则”,但是与工厂方法模式不同的是,工厂方法模式在新增一个具体的产品时候会需要增加对应的工厂,但是抽象工厂模式只有在新增一个系列的具体产品才需要新增工厂,就是说工厂方法模式只可以创建一个单一的具体产品,而抽象工厂模式可以创建多个且属于一个类型的具体产品。

缺点:产品族扩展比较繁琐,当新增一个系列的某一个产品时,需要增加具体的产品类,还需要增加对应的工厂类。

五、策略模式

策略模式是一种行为型模式,它将对象和行为拆开,将具体的行为定义为一个行为接口和具体的实现,把它们一个个封装起来,并且可以使他们互相替换。

5.1、UML类图

5.2、角色设计

角色描述
策略抽象接口用于定义若个算法的表示
具体策略类是策略抽象接口的具体实现,说白了就是重写策略的方法
策略上下文类上下文包含用策略(接口)声明的变量,委托策略变量调用具体策略所实现的策略接口中的方法(

5.3、代码实现

1、定义支付策略接口

public interface PayStrategy {

    void pay();

}

2、微信支付策略实现类

public class WXStrategy implements PayStrategy{

    @Override
    public void pay() {
        System.out.println("微信支付");
    }

}

3、支付宝策略实现类

public class ZFBStrategy implements PayStrategy{

    @Override
    public void pay() {
        System.out.println("支付宝支付");
    }

}

4、策略上下文实现

public class StrategyContext {

    private PayStrategy payStrategy;

    public StrategyContext(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }

    public void pay(){
        this.payStrategy.pay();
    }

}

5、主方法测试 

public class Main {
    public static void main(String[] args) {

        PayStrategy wx = new WXStrategy();
        PayStrategy zfb = new ZFBStrategy();

        StrategyContext wxContext = new StrategyContext(wx);
        StrategyContext zfbContext = new StrategyContext(zfb);

        wxContext.pay();
        zfbContext.pay();

    }
}

5.4、总结

优点:策略模式完全符合了“开闭原则”,用户可以在不修改原有系统基础的选择上,可以灵活的切换对应的行为,同时也提供了管理相关的算法族的方法和替换集成关系的方法,最后也避免了多重的条件语句。

缺点:策略模式会产生很多的策略类,客户端必须要知道所有的策略类来自我决定要使用哪一种策略。

六、使用工厂模式+策略模式消除冗余if-else语句

这边例如有一个需求:后端需要接收前端传递过来的修改的字段类型和修改具体内容去修改某个指定的字段,这边列举了两个例子,需要修改一个人的姓名或者是住址,如果是用传统的if-else语句是这样写的.

        String bulkType = "address";
        String bulkStr = "上海";
        if("name".equals(bulkType)){
            System.out.println("修改姓名为:" + bulkStr);
        } else if ("address".equals(bulkType)) {
            System.out.println("修改住址为:"+ bulkStr);
        }

如果修改的类型有5个甚至更多,那就会有很多冗余的if-else语句,这样就会显得整体代码不够优雅,非常臃肿,所以这边就需要我们用到java的设计模式去优化掉这段if-else语句,代码如下: 

1、策略接口

public interface Revise {

   public void execute(String str);

}

2、姓名修改策略类

public class ReviseName implements Revise{
    @Override
    public void execute(String str) {
        System.out.println("修改姓名为:" + str);
    }
}

3、地址修改策略类

public class ReviseAddress implements Revise{

    @Override
    public void execute(String str) {
        System.out.println("修改住址为:"+str);
    }

}

4、策略工厂类

public class ReviseFactory {

    private static Map<String, Revise> map = new HashMap<>();

    static {
        map.put("name", new ReviseName());
        map.put("address", new ReviseAddress());
    }

    public static Revise getReviseStrategy(String str) {
        return map.get(str);
    }
    
}

5、测试运行

    public static void main(String[] args) {
        String bulkType = "address";
        String bulkStr = "上海";
        //获取对应的策略接口
        Revise revise = ReviseFactory.getReviseStrategy(bulkType);
        // 调用具体策略方法
        revise.execute(bulkStr);
    }

这样我们就完整使用了这2种模式优雅的消除的冗余的if-else语句。

七、Gitee源码

目前博主也还在努力学习java的设计模式,这里做了一个目前学习的分享,整体思路清晰通俗易懂。

这是源码地址:java使用策略模式和工厂模式来消除冗余的if-else语句

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/697241.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

把Jar打包为Maven 把jar打包为maven 将java项目打包为maven 将Java项目打包为Maven

把Jar打包为Maven 把jar打包为maven 将java项目打包为maven 将Java项目打包为Maven 自己写了一个通用SDK Jar包&#xff0c;但是现在的项目都是Maven项目&#xff0c;需要把Jar打包为Maven格式&#xff0c;输出到本地Maven仓库&#xff0c;在项目中可以引用查看Maven是否安装打…

nginx进行反向代理

Nginx是一个开源的高性能Web服务器和反向代理服务器。它最初是由Igor Sysoev在2004年开发的&#xff0c;现在由一个全球性的社区维护和支持。 Nginx的主要特点包括&#xff1a; 高性能&#xff1a;Nginx使用事件驱动模型&#xff0c;可以处理高并发请求&#xff0c;具有出色的…

A* 算法研究(附 Python / C++ 实现)

A* 算法研究 参考 A*寻路算法详解 #A星 #启发式搜索 路径规划之 A* 算法 最短路搜索-从Dijkstra到Best-First再到A-Star 路径规划算法学习笔记&#xff08;一&#xff09;&#xff1a;A*算法 A*算法寻路&#xff08;C代码实现&#xff09; 《基于A*算法的自动泊车全局路径规划…

恒生电子联合恒生聚源发布数智金融新品,聚焦大模型技术金融业务应用

6月28日&#xff0c;恒生电子和旗下子公司恒生聚源正式发布基于大语言模型技术打造的数智金融新品&#xff0c;金融智能助手光子和全新升级的智能投研平台WarrenQ。此外&#xff0c;恒生电子金融行业大模型LightGPT也首次对外亮相&#xff0c;并公布最新研发进展。 恒生电子董…

升级Win10后多了个恢复分区,有什么用

很多用户从Win7/Win8/Win8.1升级到Win10之后发现电脑硬盘上多出了一个“恢复分区”&#xff0c;64位系统下这个分区大小在450MB左右。那么为什么会多出这样一个分区&#xff0c;这个分区又是干什么的&#xff0c;能不能删除呢&#xff1f;下面以MBR硬盘情况为例来说明。 1.全盘…

MySQL数据库 SQL语言命令总结 数据类型、运算符和聚合函数汇总

数据库&#xff1a;存储数据的仓库&#xff0c;有组织的进行存储数据。SQL&#xff1a;操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准。常用的关系型数据库管理系统&#xff1a;Oracle、MySQL、Microsoft SQL Server等。 Oracle是大型收费数据库&…

初识express/路由/中间件

路由的概念 模块化路由 中间件(要有输入输出) 简化版本 全局生效中间件 局部生效中间件 注意事项 中间件分类 内置中间件,解析请求体/url-encoded 自定义中间件 使用querystring模块解析请求体数据 编写接口 ​​​​​​​

x86_64(intel64、amd64)和ARM64的区别以及发展

文章目录 区别引用 区别 ARM64架构 ARM 公司研发的&#xff0c;用的是精简指令集&#xff08;追求节能&#xff0c;低功耗&#xff09;。通常用于手机、平板等CPU&#xff0c;目前笔记本电脑也会采用ARM64构架的CPU&#xff0c;比如mac m1就是arm64(查看命令&#xff1a;uname…

智能佳—LoCoBot WX250 6自由度

&#xff08;用于科研与教学的ROS智能车&#xff09; LoCoBot是用于映射、导航和操纵&#xff08;可选&#xff09;等ROS研究的智能车&#xff0c;研究人员、教育工作者和学生都可以使用LoCoBot专注于高级代码的开发&#xff0c;而不是专注硬件和构建低级代码。通过开放的源代码…

EasyExcel实现指定列自定义导出

效果展示 全部导出 自定义导出 代码实现 1.引入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.1</version> </dependency> 2.实体类 Data public class User {Exc…

vue PC端完成电子签名

最近接到一任务&#xff0c;有一个功能&#xff0c;重来没有遇到过。就是电子签名 看了原型其他基本都是对接口、写表单&#xff0c;难度不大&#xff0c;先把电子签名给攻克了起。 因为项目是vue 所有使用了 vue-esign 组件 1. 安装依赖 npm install vue-esign --save2.使用…

C++中的关联容器map下标运算符[]使用分析

最近使用到C中的map&#xff0c;发现一个问题&#xff0c;如果一个键不存在时&#xff0c;下标运算符会创建一个新的元素&#xff0c;其关键字为键。 一&#xff0c;问题重现 首先看一下问题描述&#xff1a; 本题要求读入 N 名学生的成绩&#xff0c;将获得某一给定分数的学生…

最细接口自动化测试yaml框架,超全详解,一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 YAML文件介绍 YAM…

津津乐道设计模式 - 责任链模式详解(教你更优雅的处理商城下单业务)

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

Linux系统的目录结构与基本命令

目录 Linux系统使用注意 Linux严格区分大小写 Linux文件"扩展名" Linux系统中常见的后缀名称&#xff1a; Linux中所有内容以文件形式保存 Linux中存储设备都必须在挂载之后才能使用 Linux系统的目录结构 Linux分区与Windows分区 Linux系统文件架构 Linux系…

用AI帮助小学一年级记住常用字

这几天娃就要一年级毕业放假了&#xff0c;感觉时间过得太快了。再开学就要上二年级&#xff0c;可汉字表上的区区三四百字&#xff0c;咋就那么的难读&#xff1f;难记&#xff1f;喊他们来认字&#xff0c;拉都拉不过来。哎&#xff0c;愁啊&#xff0c;替他们焦虑。突发奇想…

Docker发布VUE vhr微人事前端(Nginx 403 forbidden)

本文代码来源于&#xff08;感谢作者&#xff09; GitHub - lenve/vhr: 微人事是一个前后端分离的人力资源管理系统&#xff0c;项目采用SpringBootVue开发。 发布过程参考博主 【Docker】使用docker容器发布vue项目_docker 发布vue_TOP灬小朋友的博客-CSDN博客 1.创建Do…

食品空压机数据采集远程监控系统解决方案

食品行业是一个需求量大、安全标准高、竞争激烈的行业。随着人们消费水平的提升&#xff0c;对食品的品质、口味、营养、卫生等方面有了更高的要求。食品空压机是食品生产过程中不可缺少的设备&#xff0c;它可以提供稳定的压缩空气&#xff0c;用于食品加工、包装、运输等环节…

大聪明教你学Java | 深入浅出聊 ThreadPoolExecutor

前言 🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。 🍊支持作者: 点赞👍、关注💖、留言💌~ 在《阿里巴巴 Java 开发手册》中有这么一个强制要求:“线程池不允许使用 Executors 去创建,而是…

6月第4周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩)发布!

飞瓜轻数发布2023年6月19日-6月25日飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营能力强的B…