html静态网站下载,wordpress导航怎么添加文章,电商网站建设思路,重庆做网络优化公司电话文章目录 应用场景存在问题解决方案继续延伸 应用场景
假设有这样的业务场景#xff0c;大数据系统把文件推送过来#xff0c;根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码#xff1a;
public class Question {public static void main(String[] args… 文章目录 应用场景存在问题解决方案继续延伸 应用场景
假设有这样的业务场景大数据系统把文件推送过来根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码
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 MapString, IFileStrategy iFileStrategyMap new ConcurrentHashMap();/*** 初始化策略.** param applicationContext Spring应用上下文* throws BeansException*/Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {MapString, 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 MapLinkageTriggerSource, 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);