SpringBoot中策略模式+工厂模式业务实例(接口传参-枚举类查询策略映射关系-执行不同策略)规避大量if-else

场景

设计模式-策略模式在Java中的使用示例:

设计模式-策略模式在Java中的使用示例_java 策略模式示例_霸道流氓气质的博客-CSDN博客

上面讲了策略模式在Java中的使用示例。

下面看一个在SpringBoot中的实际使用示例。

业务场景:

有多个煤矿,信号灯有多个厂家/规则,每个煤矿对应一种信号灯。

需要编写通用接口,根据传递的请求码不同获取到该煤矿对应的信号灯规则,并执行对应的信号灯规则获取数据。

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主

实现

1、新建信号灯规则接口类

public interface SignalLightRules {

    List<SignalrightDevsDTO> getSignalrightDevsDtoList(String mineApiCode);

}

其中方法getSignalrightDevsDtoList是用来获取信号灯信息。

2、新建厂家1/规则1的实现类

@Component(Constants.SIFANGJI)
public class SiFangJiSignalLightRules implements SignalLightRules{

    @Autowired
    private SNDataUploadServiceImpl snDataUploadService;

    @Autowired
    private BusSignallightControlService busSignallightControlService;

    @Override
    public List<SignalrightDevsDTO> getSignalrightDevsDtoList(String mineApiCode) {
        //获取所有信号灯id
        List<Long> signalLightIdList = busSignallightControlService.selectBusSignallightControlIdList();
        List<SignalrightDevsDTO> signalrightDevsDtoList = snDataUploadService.getSignalrightDevsDtoList(signalLightIdList,mineApiCode);
        return signalrightDevsDtoList;
    }
}

注意这里添加注解

@Component(Constants.SIFANGJI)

并且名称使用了常量类的常量。

附常量类

public class Constants {

    public static final String SIFANGJI = "sifangji";

    public static final String KEERMA = "keerma";

}

然后在具体获取信号灯数据的方法中调用的两个service都是跟本厂家/规则具体业务相关。

3、新建厂家2/规则2的实现类

@Component(Constants.KEERMA)
public class KeErMaSignalLightRules implements SignalLightRules{
    @Override
    public List<SignalrightDevsDTO> getSignalrightDevsDtoList(String mineApiCode) {
        return new ArrayList<>();
    }
}

这里具体业务实现直接返回一个空list。

4、新建信号灯工厂类,用来获取对应的信号灯规则

@Component
public class SignalLightRulesFactory {

    //Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id 即前面@Component注解指定的名称,value值则为对应的策略实现类
    @Autowired
    Map<String,SignalLightRules> signalLightRulesStrategy;

    private static final SignalLightRules DEFAULT_RULES = new SiFangJiSignalLightRules();

    public  SignalLightRules getSignalLightRules(String signalLightKey){
        SignalLightRules signalLightRules = signalLightRulesStrategy.get(signalLightKey);
        return signalLightRules == null?DEFAULT_RULES:signalLightRules;
    }
}

注意这里添加@Component注解,并且在存储规则的map上添加@Autowired,

Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id 即前面@Component注解指定的名称,

value值则为对应的策略实现类。

5、不同的煤矿使用的信号灯规则可能相同也可能不同,所以需要配置一个煤矿与信号灯规则的映射关系的存储。

import com.badao.demo.constant.Constants;
import org.springframework.lang.Nullable;
import java.util.HashMap;
import java.util.Map;

public enum MineMessageEnum
{
    JJT("jjt", "0001","名称1", Constants.SIFANGJI),
    ZLW("zlw", "0002","名称2",Constants.SIFANGJI),
    CCL("ccl", "0003","名称3",Constants.KEERMA);

    private final String apiCode;
    private final String mineCode;
    private final String mineName;
    private final String signalRule;

    private static final Map<String, MineMessageEnum> mappings = new HashMap<>();

    static
    {
        for (MineMessageEnum messageEnum : values())
        {
            mappings.put(messageEnum.apiCode, messageEnum);
        }
    }

    @Nullable
    public static MineMessageEnum resolve(@Nullable String mineApiCode)
    {
        return (mineApiCode != null ? mappings.get(mineApiCode) : null);
    }

    MineMessageEnum(String apiCode, String mineCode, String mineName,String signalRule)
    {
        this.apiCode = apiCode;
        this.mineCode = mineCode;
        this.mineName = mineName;
        this.signalRule = signalRule;
    }

    public String getApiCode() {
        return apiCode;
    }

    public String getMineCode() {
        return mineCode;
    }

    public String getMineName() {
        return mineName;
    }

    public String getSignalRule() {
        return signalRule;
    }
}

这里使用枚举类来实现,存储apiCode与signalRule的对应关系。

然后再static静态代码块中初始化,将所有的映射关系存储进map,并且提供一个根据key获取value的方法。

6、在实际业务Controller层中

    @GetMapping("/signalright_devs")
    public AjaxResult SignalRightDevs(@RequestParam("mineApiCode") String mineApiCode)
    {
        try{
            MineMessageEnum resolve = MineMessageEnum.resolve(mineApiCode);
            if(null == resolve){
                return AjaxResult.error(HttpStatus.BAD_REQUEST, Constants.NO_API_CODE);
            }else {
                SignalLightRules signalLightRules = signalLightRulesFactory.getSignalLightRules(resolve.getSignalRule());
                List<SignalrightDevsDTO> signalrightDevsDTOS = signalLightRules.getSignalrightDevsDtoList(mineApiCode);
                if(null != signalrightDevsDTOS && signalrightDevsDTOS.size()>0){
                    return AjaxResult.success(signalrightDevsDTOS);
                }else {
                    return AjaxResult.success();
                }
            }
        }catch (Exception exception){
            System.out.println("SignalRightDevs:"+exception.getMessage());
            return AjaxResult.error(HttpStatus.ERROR,Constants.SERVER_ERROR);
        }
    }

首先接口传递apiCode参数,并且判断是否为合法参数,如果不存在则返回自定义错误提示。

存在则获取对应的信号灯规则,通过

signalLightRulesFactory.getSignalLightRules(resolve.getSignalRule());

获取具体规则,注意上面注入信号灯工厂。

    @Autowired
    private SignalLightRulesFactory signalLightRulesFactory;

7、测试

传递规则1对应的apicode,返回对应业务规则数据

 

传递规则2对应的apicode,返回空数据

 

传递非法参数

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智安网络|网络安全威胁越来越多,教你如何全方面应对

随着互联网的普及和发展&#xff0c;各大网站已经成为人们获取信息和交流的主要平台。然而&#xff0c;随着网络攻击和恶意软件的威胁不断增加&#xff0c;网站经常成为攻击者的目标。因此&#xff0c;在建立和维护网站系统时&#xff0c;必须采取强大的安全措施。 一、网站系…

第四十二章 Unity 下拉框 (Dropdown) UI

本章节我们介绍下拉框 (Dropdown)&#xff0c;我们点击菜单栏“GameObject”->“UI”->“Dropdown”&#xff0c;然后调整它的位置&#xff0c;效果如下 其实它的本质就是一个下拉列表&#xff0c;然后选择列表中的一个选项而已。大家在很多网页中应该可以看到类似的UI元…

Vue框架

目录 简单介绍 MVVM 下载安装Node.js 安装Vue.js插件 新建Vue.js项目 下载vue依赖库 Vue工程目录结构 修改代码模板 vue组件中&#xff0c;添加模型数据 Vue双向绑定 动态绑定 vue组件中&#xff0c;显示图片 单选框绑定 复选框绑定 Vue的script表达式 Vue实例声…

MySQL概述 -- 数据模型SQL简介DDL数据库操作

一. 数据模型 介绍完了Mysql数据库的安装配置之后&#xff0c;接下来我们再来聊一聊Mysql当中的数据模型。学完了这一小节之后&#xff0c;我们就能够知道在Mysql数据库当中到底是如何来存储和管理数据的。 在介绍 Mysql的数据模型之前&#xff0c;需要先了解一个概念&#x…

【Linux】进程地址空间

目录 引入 进程地址空间 虚拟地址与物理地址 如何理解虚拟地址的不同区域 写时拷贝 动态开辟的细节 为什么存在进程地址空间 避免地址被随意访问 进程管理和内存管理解耦合 使进程用统一的视角看待代码和数据 引入 &#x1f383;我们写一个这样的程序&#xff0c;运…

算法记录 | Day50 动态规划

123.买卖股票的最佳时机III 思路&#xff1a; 1.确定dp数组以及下标的含义 最多可完成两笔交易意味着总共有三种情况&#xff1a;买卖一次&#xff0c;买卖两次&#xff0c;不买卖。 具体到每一天结束总共有 5 种状态&#xff1a; 未进行买卖状态&#xff1b;第一次买入状…

springboot - spring.factories

spring.factories 是什么&#xff1f; spring.factories 是 Spring Boot 自动配置的核心机制之一&#xff0c;它用于自动注册 Spring Boot 中的各种自动配置类&#xff0c;从而实现自动化配置的目的。在 Spring Boot 应用程序启动时&#xff0c;Spring Boot 会自动扫描 classp…

深度解读:《数字孪生世界白皮书(2023)》全方位剖析

2023年初&#xff0c;中国信息通信研究院发布了《数字孪生城市产业图谱研究报告&#xff08;2022&#xff09;》&#xff0c;报告中提出我国数字孪生产业四阶段体系&#xff0c;2020年到2030年是我国数字孪生产业增长期&#xff0c;当前数字孪生市场需求和技术均处于高速发展阶…

5月跳槽有风险,不跳也有?

今天讲讲跳槽。 说实话跳槽是为了寻求更好的发展&#xff0c;但在跳槽前我们也不能确定下家就是更好的归宿&#xff0c;这就更加需要我们审慎地去对待&#xff0c;不能盲目跳槽。 其次&#xff0c;我们离职和跳槽&#xff0c;其中的原因很大一部分是目前薪资不符合预期。 那…

C. Permutation Game(博弈 + 拓扑的思想)

Problem - C - Codeforces 经过漫长的一天&#xff0c; Aice和Bob决定玩一个小游戏。游戏棋盘由n个格子组成&#xff0c;在一条直线上&#xff0c;编号从1到n,每个格子包含一个数字4;,qy在1到n.之间&#xff0c;而且没有两个格子包含相同的数字。 一个棋子被放在其中一个格子里…

什么牌子蓝牙耳机好用不贵?国产性价比高的蓝牙耳机推荐

相较于有线耳机&#xff0c;无线蓝牙耳机更便携、功能更丰富&#xff0c;不用受到耳机孔与线的限制。那么&#xff0c;什么牌子的蓝牙耳机好用不贵&#xff1f;针对这个问题&#xff0c;我给大家推荐几款国产性价比高的蓝牙耳机&#xff0c;可以当个参考。 一、南卡小音舱Lite…

Spring使用注解存储和读取对象

文章目录 一、存储Bean对象配置扫描添加注解存储Bean对象注解使用范围Bean的命名五大类注解的关系为什么需要五大类注解? 二、方法注解BeanBean重命名 三、对象注入属性注入Setter注入构造方法注入Autowired 和 Resource 的区别 一、存储Bean对象 之前我们存储Bean时&#xff…

5 Redis缓存穿透、击穿、雪崩、分布式锁、布隆过滤器

1 Redis 应用问题解决 1.1 缓存穿透 1.1.1 问题描述 key 对应的数据在数据源并不存在&#xff0c;每次针对此 key 的请求从缓存获取不到&#xff0c;请求都会压到数据源&#xff08;数据库&#xff09;&#xff0c;从而可能压垮数据源。比如 用一个不存在的用户 id 获取用户…

一份标准的软件测试方案模板

第一章 概述 ​ 软件的错误是不可避免的&#xff0c;所以必须经过严格的测试。通过对本软件的测试&#xff0c;尽可能的发现软件中的错误&#xff0c;借以减少系统内部各模块的逻辑&#xff0c;功能上的缺陷和错误&#xff0c;保证每个单元能正确地实现其预期的功能。检测和排…

亚马逊云科技开启您的云财务管理之旅:云财务运营

亚马逊云科技“开启您的云财务管理之旅”系列内容提出了关于如何启动和实施一个成功的云财务管理CFM战略的建议。云财务管理CFM的三个原则&#xff1a;SEE-查看、SAVE-节省和PLAN-计划。接下来介绍的是第四个阶段&#xff1a;RUN-运营。 在这一阶段&#xff0c;可以了解云财务管…

vue 做一个文本展示 点击文本弹出element ui的时间选择器 但不会出现element ui时间组件的那个输入框

我们先来创建一个vue2项目 引入element ui 然后 找到一个组件 这样写 <template><div><el-date-pickerv-model"value"type"datetimerange"align"right"unlink-panelsrange-separator"至"start-placeholder"开始日…

C/C++的命名空间和调用函数的详细讲解

目录 空函数 调用函数 调用 执行流程 命名空间 在创建函数时&#xff0c;必须编写其定义。所有函数定义包括以下组成部分&#xff1a; 名称&#xff1a;每个函数都必须有一个名称。通常&#xff0c;适用于变量名称的规则同样也适用于函数名称。形参列表&#xff1a;调用函…

手机摄影笔记(二)

第5章 镜头语言 镜头语言分类&#xff08;8个&#xff09;&#xff1a; 推&#xff1a;从远到近 拉&#xff1a;从近到远 摇&#xff1a;机位固定&#xff0c;旋转手机拍全景或者跟着拍摄对象进行摇摄&#xff08;跟摇&#xff09;.通常用此方式来介绍环境时&#xff0c;表现的…

开放原子训练营(第三季)inBuilder低代码开发实验室---报销单录入系统

作为一名低代码初学者&#xff0c;我使用inBuilder系统设计了一款报销单录入系统&#xff0c;实现了报销单录入与显示报销单列表的功能&#xff08;如图1与图2所示&#xff09;&#xff0c;并获得了很多开发心得。从inBuilder系统的优点、缺点以及开发过程三方面出发&#xff0…

基于SpringBoot,vue的家政服务平台的设计与实现

背景 以往的家政服务管理平台的管理&#xff0c;一般都是纸质文件来管理家政服务信息&#xff0c;传统的管理方式已经无法满足现代人们的需求&#xff1b;使用家政服务管理平台, 首先可以大幅提高家政服务信息检索&#xff0c;只需输入家政服务相关信息就能在数秒内反馈想要的…