假设有这样的业务场景,大数据系统把文件推送过来,根据不同类型采取不同的解析方式。多数的小伙伴就会写出以下的代码:
- if(type=="A"){
- //按照A格式解析
- }else if(type=="B"){
- //按B格式解析
- }else{
- //按照默认格式解析
- }
这个代码可能会存在哪些问题呢?
说得专业一点的话,就是以上代码,违背了面向对象编程的开闭原则以及单一原则。
如果你的代码就是酱紫:有多个
if...else
等条件分支,并且每个条件分支,可以封装起来替换的,我们就可以使用策略模式来优化。
策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的的客户。
策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
策略模式怎么使用呢?酱紫实现的:
举例如下
- public interface IFileStrategy {
-
- //属于哪种文件解析类型
- FileTypeResolveEnum gainFileType();
-
- //封装的公用算法(具体的解析方法)
- void resolve(Object objectparam);
- }
- //A 类型策略具体实现
- @Component
- public class AFileResolve implements IFileStrategy {
-
- @Override
- public FileTypeResolveEnum gainFileType() {
- return FileTypeResolveEnum.File_A_RESOLVE;
- }
-
- @Override
- public void resolve(Object objectparam) {
- logger.info("A 类型解析文件,参数:{}",objectparam);
- //A类型解析具体逻辑
- }
- }
-
- //B 类型策略具体实现
- @Component
- public class BFileResolve implements IFileStrategy {
-
- @Override
- public FileTypeResolveEnum gainFileType() {
- return FileTypeResolveEnum.File_B_RESOLVE;
- }
-
-
- @Override
- public void resolve(Object objectparam) {
- logger.info("B 类型解析文件,参数:{}",objectparam);
- //B类型解析具体逻辑
- }
- }
-
- //默认类型策略具体实现
- @Component
- public class DefaultFileResolve implements IFileStrategy {
-
- @Override
- public FileTypeResolveEnum gainFileType() {
- return FileTypeResolveEnum.File_DEFAULT_RESOLVE;
- }
-
- @Override
- public void resolve(Object objectparam) {
- logger.info("默认类型解析文件,参数:{}",objectparam);
- //默认类型解析具体逻辑
- }
- }
3. 使用策略模式
如何使用呢?我们可以借助spring
的生命周期,使用ApplicationContextAware
接口,把对用的策略,初始化到map
里面。然后对外提供resolveFile
方法即可。
使用StrategyUseService#resolveFile方法即可。
- @Component
- public class StrategyUseService implements ApplicationContextAware{
-
-
- private Map<FileTypeResolveEnum, IFileStrategy> iFileStrategyMap = new ConcurrentHashMap<>();
-
- public void resolveFile(FileTypeResolveEnum fileTypeResolveEnum, Object objectParam) {
- IFileStrategy iFileStrategy = iFileStrategyMap.get(fileTypeResolveEnum);
- if (iFileStrategy != null) {
- iFileStrategy.resolve(objectParam);
- }
- }
-
- //把不同策略放到map
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- Map<String, IFileStrategy> tmepMap = applicationContext.getBeansOfType(IFileStrategy.class);
- tmepMap.values().forEach(strategyService -> iFileStrategyMap.put(strategyService.gainFileType(), strategyService));
- }
- }