网站建设算固定资产吗,网络规划设计师教程下载,响应式网站开发用什么软件,中国建筑工程平台网前言
在不同的场景下#xff0c;执行不同的业务逻辑#xff0c;在日常工作中是很寻常的事情。比如#xff0c;订阅系统。在收到阿里云的回调事件、与收到AWS的回调事件#xff0c;无论是收到的参数#xff0c;还是执行的逻辑都可能是不同的。为了避免#xff0c;每次新增…前言
在不同的场景下执行不同的业务逻辑在日常工作中是很寻常的事情。比如订阅系统。在收到阿里云的回调事件、与收到AWS的回调事件无论是收到的参数还是执行的逻辑都可能是不同的。为了避免每次新增一种场景就要改变原有的代码结构比如改变原有逻辑添加 if-else结构一种可行的方案是使用策略模式。
策略模式
贴个链接 简单来说就是根据请求方的类型执行特定的业务逻辑。
问题点
网络上大部分实现策略模式的代码很多在将具体的策略注入到Map中时是以硬编码的方式实现的比如掘金上的这篇文章如何优雅的将设计模式运用到实际项目中去? 在工作中借鉴使用截图 这种方案虽然可以实现策略模式但是每次新增策略都要修改这个集合。期望的方案是新增的策略自动注入到map中而不必手动添加。 为了解决新增策略时要修改map的情况调研之后发现有两种方案
美团文章推介的 基于单例的方式每次启动时自动将策略注入到map中。掘金上另一种方案基于注解反射的方式动态将策略加载到map中。
相比美团的方案更加优秀代码改动少且性能高。不过本次以方案2为例说明。
代码实现
业务场景
需要提供给外部云厂商回调API当云服务发生告警时调用此API将告警事情同步到服务使用方。 考虑点
因为每家厂商的回调参数各有不同此时需要定义一个回调对象基类每个云厂商对应的回调对象继承这个基类并实现添加其特定的属性。因为API是放开到公网上的因此为了避免被攻击除了从集团域名出去外还对IP进行了频控比如调用次数100次/秒。
代码结构 具体代码
定义实体类
基类
import lombok.Data;/*** author wangbin16* date 2024/1/18 15:33*/
Data
public class CloudAlertBase {/*** name alertType, value 告警类型*/private Integer alertType;/*** 业务*/private Integer business;
}
阿里云
import lombok.Data;/*** 阿里云监控告警* author wangbin16* date 2024/1/18 15:35*/
Data
public class AliyunCloudAlertAo extends CloudAlertBase {private static final long serialVersionUID 1L;/*** name alertName, value 报警名称*/private String alertName;/*** name alertState, value 报警状态*/private String alertState;/*** name curValue, value 报警发生或恢复时监控项的当前值*/private String curValue;/*** name dimensions, value 发生报警的对象*/private String dimensions;/*** name expression, value 报警规则的表达式*/private String expression;策略模式
策略基类
/*** author wangbin16* date 2024/1/18 15:41*/
public interface CloudAlertStrategy {/*** 处理云监控告警* param param*/void handleCloudAlert(CloudAlertBase param);
}
阿里云策略
Slf4j
Service
CloudAlertAnnotation(alertType CloudAlertTypeEnum.ALIYUN)
public class AliyunCloudAlertStrategy implements CloudAlertStrategy {Overridepublic void handleCloudAlert(CloudAlertBase param) {// TODO 处理阿里云监控告警// 暂时先发送给我 wangbin16SendMsgUtils sendMsgUtils new SendMsgUtils();sendMsgUtils.sendP2pPopoMsg(JSON.toJSONString(param), wangbin16xxx, 【阿里云监控告警】);}
}
策略注册
import org.reflections.Reflections;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*** author wangbin16* date 2024/1/18 15:50*/
public class AnnotationCloudAlertStrategyFactory {/*** 存储策略*/static MapInteger, CloudAlertStrategy strategyMap new HashMap();static {registerStrategy();}/*** 自动注册策略*/private static void registerStrategy() {// 通过反射获取所有的策略类Reflections reflections new Reflections(CloudAlertStrategy.class.getPackage().getName());SetClass? extends CloudAlertStrategy cloudStrategyClassSet reflections.getSubTypesOf(CloudAlertStrategy.class);if (cloudStrategyClassSet ! null) {for (Class? clazz : cloudStrategyClassSet) {// 找到类型注解自动完成策略注册if (clazz.isAnnotationPresent(CloudAlertAnnotation.class)) {CloudAlertAnnotation alertTypeAnnotation clazz.getAnnotation(CloudAlertAnnotation.class);CloudAlertTypeEnum chargeType alertTypeAnnotation.alertType();try {strategyMap.put(chargeType.getCode(), (CloudAlertStrategy) clazz.newInstance());} catch (InstantiationException | IllegalAccessException e) {e.getStackTrace();}}}}}/*** 提供注册策略接口外部只需要调用此接口接口新增策略* 策略定义时即注入这是口子*/public static void registerChargeStrategy(CloudAlertTypeEnum alertType, CloudAlertStrategy strategy) {strategyMap.put(alertType.getCode(), strategy);}
}策略选择器
Service
Slf4j
public class CloudAlertStrategySelector {public CloudAlertStrategy selector(Integer alertType) {if (alertType null) {return null;}return AnnotationCloudAlertStrategyFactory.strategyMap.get(alertType);}
}服务调用
Slf4j
Service(cloudMonitorService)
public class CloudMonitorService {Autowiredprivate CloudAlertStrategySelector cloudAlertStrategySelector;public void handleCloudMonitor(CloudAlertBase param) {logger.info(handleCloudMonitor param:{}, JSON.toJSONString(param));CloudAlertStrategy selector cloudAlertStrategySelector.selector(param.getAlertType());if (selector ! null) {selector.handleCloudAlert(param);} else {logger.error(外部云告警异常调用, param:{}, JSON.toJSONString(param));}}
}测试
调用指定的接口执行指定的逻辑