SpringBoot+策略模式+枚举类,优雅消除if-else

需求分析

公司做物联网系统的,使用nettry进行设备连接,对设备进行数据采集,根据设备的协议对数据进行解析,解析完成之后存放数据库,但是不同厂家的设备协议不同。公司系统使用了使用了函数式编程的去写了一个解析类,所有的协议解析都在同一个方法类里面了,耦合度超高,不够优雅,我决定使用策略模式对它进行优化!

策略模式

下面是原理图,跟其他大佬的差不多,主要就是抽象策略接口具体策略环境 三部分,这里不介绍策略模式了,建议去看看别的大佬写的好博客吧。

下面直接上代码!

代码实现

枚举类

现有的系统是根据协议长度来判断不同厂家的设备的,所以定义一个枚举类,len是协议的长度,beanName是具体策略 的bean名称,通过传入的协议长度获取beanName,再获取具体策略的bean,去执行具体的解析方法。

java 复制代码
public enum AnalysisEnum {

    SONGXIA(101, "songXiaAnalysisStrategy", "松下"),
    OTC(102, "OTCAnalysisStrategy", "OTC"),
    JIANGNAN(103, "jiangNanAnalysisStrategy", "江南"),

    ;


    private int len;
    private String beanName;
    private String desc;

    AnalysisEnum(int len, String beanName, String desc) {
        this.len = len;
        this.beanName = beanName;
        this.desc = desc;
    }

    public int getLen() {
        return len;
    }

    public String getBeanName() {
        return beanName;
    }

    public String getDesc() {
        return desc;
    }

    public static AnalysisEnum getAnalysisEnum(Integer len) {
        for (AnalysisEnum analysisEnum : AnalysisEnum.values()) {
            if (analysisEnum.getLen() == len) {
                return analysisEnum;
            }
        }

        throw new RuntimeException("异常");
    }
}

抽象策略接口和具体策略

java 复制代码
public interface AnalysisStrategy {

    void analysis();
}

@Component("jiangNanAnalysisStrategy")
public class JiangNanAnalysisStrategy implements AnalysisStrategy {


    @Override
    public void analysis() {
        System.out.println("解析江南协议...");
    }
}

@Component("OTCAnalysisStrategy")
public class OTCAnalysisStrategy implements AnalysisStrategy {
    @Override
    public void analysis() {
        System.out.println("解析OTC协议...");
    }
}

@Component("songXiaAnalysisStrategy")
public class SongXiaAnalysisStrategy implements AnalysisStrategy {
    @Override
    public void analysis() {
        System.out.println("解析松下协议...");
    }
}

环境

抽象策略接口 定义为Map<String, AnalysisStrategy>的value,通过spring的自动注入,所有的具体策略 实现类都会被注入到map当中,key为beanId,即@Component指定的bean名称,配合AnalysisEnum,就可以通过协议长度获取具体策略执行具体方法 ,从而优雅地消除if-else

java 复制代码
@Component
public class AnalysisContext {

    @Resource
    private Map<String, AnalysisStrategy> selectorMap;

    public void analysis(Integer len) {
        AnalysisEnum analysisEnum = AnalysisEnum.getAnalysisEnum(len);
        System.out.println("协议长度:" + len + " " + "设备:" + analysisEnum.getDesc());
        selectorMap.get(analysisEnum.getBeanName()).analysis();
    }
}

controller

java 复制代码
@RestController
@Api(tags = "策略模式")
public class StrategyController {

    @Autowired
    private AnalysisContext analysisContext;

    @GetMapping("/strategy")
    @ApiOperation("策略模式测试接口")
    public void test1(@RequestParam Integer len) {
        analysisContext.analysis(len);
    }
}

测试结果

总结

最优雅地策略模式,当然是实现了抽象策略接口之后就可以使用,但是目前本帅写的代码当中尽管优雅地消除了if-else,但不符合OOP原则,不过没办法,系统中就必须得通过协议长度去判断不同的协议,而spring中注入具体策略类是通过beanId去实现的,无法通过协议长度直接拿到具体策略类。

相关推荐
升鲜宝供应链及收银系统源代码服务2 分钟前
升鲜宝云仓供应链管理系统 数据库数据字典设计 (一)---升鲜宝生鲜配送供应链管理系统
java·生鲜配送源代码·供应链源代码·生鲜供应链源代码·企业erp源代码·云仓供应链管理系统
无限进步_4 分钟前
【C++】AVL树完全解析:从平衡因子到四种旋转
c语言·开发语言·数据结构·c++·后端·算法·github
渐儿6 分钟前
Claude Code 的 Hooks 系统
后端
Pkmer7 分钟前
古法编程: 我要的是状态模式,策略模式不要误我大计
后端·设计模式
tenggouwa7 分钟前
16GB Mac 同时开 3 个 Cursor 拯救我的mac
前端·后端
大厂数码评测员8 分钟前
2026 年家庭菜谱记录工具怎么选:从功能边界和小程序代码实现看免费与付费差异
java·开发语言·apache
twc8298 分钟前
从架构视角梳理全链路压测的核心业务链路
java·大数据·软件测试·架构·性能测试·全链路压测
ltl10 分钟前
激活函数:让网络「弯下来」的非线性魔法
后端
XS03010610 分钟前
Java基础 set集合
java·开发语言
驭渊的小故事11 分钟前
继承和多态
java·开发语言