spring boot策略模式实用: 告警模块为例

spring boot策略模式实用: 告警模块

0 涉及知识点

策略模式, 模板方法, 代理, 多态, 反射

1 需求概括

  • 场景: 每隔一段时间, 会获取设备运行数据, 如通过温湿度计获取到当前环境温湿度;
  • 需求: 对获取回来的进行分析, 超过配置的阈值需要产生对应的告警

2 方案设计

告警的类别往往容易变化, 比如今天只有温度过高告警, 明天可能就要增加一个温度过低告警, 所以设计最好可以满足开闭原则, 方便后续对功能进行删减;

整体思路如下:

  • 顶层接口Handler 定义了两个方法, check 用于校验是否应该产告警, 入参可以选择传入告警配置和需要判定对象, handle方法主要用于告警的具体处理过程, 如之前是否存在告警等;
  • 统一抽象类AbstractHandler 中, 重写handle 方法, 作为模版方法, 一般不同的告警处理流程是相近的, 可以抽象处理, 如都要判断进行判断当前是否已存在告警等; 抽象类中还可以抽象出通用的方法和声明通用属性;
  • 各个具体实现类, 如TemperatureHandler 等, 各类告警的具体实例对象, 如果告警判定方式或处理流程上有不同, 可以选择性的重写check 方法或handle方法, 由于java的多态, 程序运行时会选择正确处理方式;

为了保证模块的完整性, 增加代理类屏蔽告警的内部处理逻辑, 外部统一通过代理类调用;

3 代码实现

  • 接口

    java 复制代码
    /**
     * 顶级接口
     * @author lixiyuan
     */
    public interface Handler {
    
        boolean check(AlarmConfig config, Object data);
    
        void handle(AlarmConfig config, Integer id, Object data);
    }
  • 抽象类

    java 复制代码
    /**
     * 抽象类, 抽取通用字段/方法, 实现模板方法
     * @author lixiyuan
     */
    public class AbstractHandler implements Handler {
    
        @Autowired
        private CurrentAlarmService currentAlarmService;
    
        @Override
        public boolean check(AlarmConfig config, Object data) {
            return false;
        }
    
        @Override
        public void handle(AlarmConfig config, Integer id, Object data) {
            // 获取当前存在的告警
            CurrentAlarm current = currentAlarmService.getCurrentAlarmById();
            // 比较阈值
            boolean check = check(config, data);
    
            // 为true发生告警
            if (check) {
                if (current == null) {
                    // 创建告警
                    currentAlarmService.save();
                } else {
                    // 更新告警
                    currentAlarmService.update();
                }
            } else {
                if (current != null) {
                    // 结束告警
                    currentAlarmService.finish();
                }
            }
        }
    
        /**
         * 反射获取属性值
         */
        protected String getValueByField(Object obj, String fieldName) {
            if (obj == null) {
                return "";
            }
            try {
                Field field = obj.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Object value = field.get(obj);
                return value == null ? "" : value.toString();
            } catch (NoSuchFieldException | IllegalAccessException e) {
                System.out.println();
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 如果判定方法比较通用, 也可以在这里定义好, 各个子类调用一下就行
         */
        protected boolean commonCompare() {
            return false;
        }
    }
  • 实现子类

    java 复制代码
    /**
     *
     * @author lixiyuan
     */
    @Component
    public class HumidityHandler extends AbstractHandler {
    
        @Override
        public boolean check(AlarmConfig config, Object data) {
            // 通过反射获取实时数据
            String humidity = getValueByField(data, "humidity");
            // 拿到配置中的阈值,然后比较, 略
            return false;
        }
    }
    
    
    /**
     *
     * @author lixiyuan
     */
    @Component
    public class TemperatureHandler extends AbstractHandler {
    
        @Override
        public boolean check(AlarmConfig config, Object data) {
            // 通过反射获取实时数据
            String humidity = getValueByField(data, "temperature");
            // 拿到配置中的阈值,然后比较, 略
            return false;
        }
    }

    代码详见: [完成代码](nanqiangli/wushixian (github.com))

相关推荐
why1515 小时前
腾讯(QQ浏览器)后端开发
开发语言·后端·golang
浪裡遊5 小时前
跨域问题(Cross-Origin Problem)
linux·前端·vue.js·后端·https·sprint
声声codeGrandMaster5 小时前
django之优化分页功能(利用参数共存及封装来实现)
数据库·后端·python·django
呼Lu噜5 小时前
WPF-遵循MVVM框架创建图表的显示【保姆级】
前端·后端·wpf
bing_1585 小时前
为什么选择 Spring Boot? 它是如何简化单个微服务的创建、配置和部署的?
spring boot·后端·微服务
学c真好玩6 小时前
Django创建的应用目录详细解释以及如何操作数据库自动创建表
后端·python·django
Asthenia04126 小时前
GenericObjectPool——重用你的对象
后端
Piper蛋窝6 小时前
Go 1.18 相比 Go 1.17 有哪些值得注意的改动?
后端
excel6 小时前
招幕技术人员
前端·javascript·后端
盖世英雄酱581366 小时前
什么是MCP
后端·程序员