当前位置: 首页 > news >正文

设计模式之策略模式-工作实战总结与实现

文章目录

  • 应用场景
  • 存在问题
  • 解决方案
  • 继续延伸

应用场景

假设有这样的业务场景,大数据系统把文件推送过来,根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码:

public class Question {public static void main(String[] args) {String type = "";if (type == "A") {//按照A格式解析} else if (type == "B") {//按B格式解析} else {//按照默认格式解析}}
}

存在问题

  • 1、如果分支变多,这里的代码就会变得臃肿,难以维护,可读性低。
  • 2、如果你需要接入一种新的解析类型,那只能在原有代码上修改。

说得专业一点的话,就是以上代码,违背了面向对象编程的开闭原则以及单一原则。

  • 开闭原则(对于扩展是开放的,但是对于修改是封闭的):增加或者删除某个逻辑,都需要修改到原来代码
  • 单一原则(规定一个类应该只有一个发生变化的原因):修改任何类型的分支逻辑代码,都需要改动当前类的代码。

解决方案

如果你的代码就是酱紫:有多个if…else等条件分支,并且每个条件分支,可以封装起来替换的,我们就可以使用策略模式来优化。

/*** 策略模式:* 一个接口或者抽象类,里面两个方法(一个方法匹配类型,一个可替换的逻辑实现方法)* 不同策略的差异化实现(就是说,不同策略的实现类)*/
public interface IFileStrategy {/*** 解析属于哪种文件类型,也可以继续优化** @return 文件类型*/String getFileType();/*** 封装的公用算法(具体的解析方法)** @param param*/void process(Object param);
}@Component
public class AFileResolve implements IFileStrategy {@Overridepublic String getFileType() {return DbDriverClassNameTypeEnum.MYSQL.getType();}@Overridepublic void process(Object param) {System.out.println("A类型文件解析具体逻辑");}
}@Component
public class BFileResolve implements IFileStrategy {@Overridepublic String getFileType() {return DbDriverClassNameTypeEnum.POSTGRES.getType();}@Overridepublic void process(Object param) {System.out.println("B类型文件解析具体逻辑");}
}@Component
public class DefaultResolve implements IFileStrategy {@Overridepublic String getFileType() {return DbDriverClassNameTypeEnum.ORACLE.getType();}@Overridepublic void process(Object param) {System.out.println("默认类型文件解析具体逻辑");}
}
/*** 如何使用呢?* 我们借助spring的生命周期,使用ApplicationContextAware接口,把对用的策略,初始化到map里面。然后对外提供resolveFile方法即可。* ApplicationContextAware接口能够轻松感知并在Spring中获取应用上下文,进而访问容器中的其他Bean和资源,* 这增强了组件间的解耦,了代码的灵活性和可扩展性,是Spring框架中实现高级功能的关键接口之一。*/
@Component
public class StrategyService implements ApplicationContextAware {private Map<String, IFileStrategy> iFileStrategyMap = new ConcurrentHashMap<>();/*** 初始化策略.** @param applicationContext Spring应用上下文* @throws BeansException*/@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {Map<String, IFileStrategy> tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);tmepMap.values().forEach(strategyService -> iFileStrategyMap.put(strategyService.getFileType(), strategyService));}/*** 统一对外提供的接口,根据类型处理文件** @param fileType* @param objectParam*/public void resolveFile(String fileType, Object objectParam) {IFileStrategy iFileStrategy = iFileStrategyMap.get(fileType);if (iFileStrategy != null) {iFileStrategy.process(objectParam);}}
}

继续延伸

在参数校验的场景中,经常会遇到根据某一个枚举字段的不同值来校验不同的入参字段,校验逻辑也是不同的,因此很容易通过IF ELSE来进行判断处理,但是这样的代码扩展性不强,CRUD痕迹很明显,不优雅!因此可以选择测罗模式进行优化。

public interface LinkageTriggerValidator {void check(LinkageRuleTriggerVo triggerVo);
}public class BizPeriodTypeValidator implements LinkageTriggerValidator {@Overridepublic void check(LinkageRuleTriggerVo triggerVo) {BizPeriodType eventType = triggerVo.getBizEventType();if (null == eventType) {throw new ParamCheckRuntimeException("业务周期事件配置缺少业务周期类型");}// todo}
}public class ReservationEventValidator implements LinkageTriggerValidator {@Overridepublic void check(LinkageRuleTriggerVo triggerVo) {ReservationEventType eventType = triggerVo.getReservationEventType();if (null == eventType) {throw new ParamCheckRuntimeException("预定事件配置缺少预定时间类型");}// todo}
}public abstract class LinkageTriggerValidatorContext {/*** 触发源校验器.*/private static Map<LinkageTriggerSource, LinkageTriggerValidator> triggerValidatorMap =new EnumMap<>(LinkageTriggerSource.class);static {triggerValidatorMap.put(LinkageTriggerSource.RESERVE_TIME, new ReservationEventValidator());triggerValidatorMap.put(LinkageTriggerSource.MANUAL_TRIGGER, new TriggerEventValidator());triggerValidatorMap.put(LinkageTriggerSource.BIZ_PERIOD, new BizPeriodTypeValidator());}public static void check(LinkageTriggerSource type, LinkageRuleTriggerVo triggerVo) {LinkageTriggerValidator validator = triggerValidatorMap.get(type);if (null == validator) {throw new UnsupportedOperationException("不支持该触发源类型:" + type);}validator.check(triggerVo);}
}
使用LinkageTriggerValidatorContext提供的check方法,统一进行参数校验即可
LinkageTriggerValidatorContext.check(trigger.getType(), trigger);
http://www.lryc.cn/news/489533.html

相关文章:

  • E - 11/22 Subsequence题解
  • PyPI 攻击:ChatGPT、Claude 模仿者通过 Python 库传播 JarkaStealer
  • 单片机学习笔记 9. 8×8LED点阵屏
  • 【大模型-智能体】AutoGen Studio测试和导出工作流程
  • 【Linux】-学习笔记04
  • 计算机网络:应用层知识点概述及习题
  • 如何构建高效的接口自动化测试框架?
  • 【C++习题】10.反转字符串中的单词 lll
  • undefined symbol: __nvJitLinkComplete_12_4, version libnvJitLink.so.12 问题解决
  • C语言——数组逐元素操作练习
  • HTML的自动定义倒计时,这个配色存一下
  • CUDA补充笔记
  • C++二级:满足条件的数的累加
  • 【山大909算法题】2014-T1
  • 【MySQL实战45讲笔记】基础篇——深入浅出索引(上)
  • 通关C语言自定义类型:联合和枚举
  • python高阶技巧一
  • Java 对象头、Mark Word、monitor与synchronized关联关系以及synchronized锁优化
  • 鸿蒙网络编程系列50-仓颉版TCP回声服务器示例
  • 软件测试基础(自动化测试、性能测试)
  • C++中的原子操作:原子性、内存顺序、性能优化与原子变量赋值
  • 游戏引擎学习第19天
  • RocketMQ: 专业术语以及相关问题解决
  • C++ 类和对象中的 拷贝构造 和 运算符重载
  • el-table最大高度无法滚动
  • Vscode写markdown快速插入python代码
  • 基于 NCD 与优化函数结合的非线性优化 PID 控制
  • 【数据分析】基于GEE实现大津算法提取洞庭湖流域水体
  • 计算机网络安全 —— 报文摘要算法 MD5
  • LeetCode 746. 使用最小花费爬楼梯 java题解