设计模式之策略模式(场景说明)

业务场景

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

if(type=="A"){
   //按照A格式解析
}else if(type=="B"){
    //按B格式解析
}else{
    //按照默认格式解析
}

这个代码可能会存在哪些问题呢

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

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

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

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

策略模式定义

        策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的的客户。

        策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。

策略模式使用步骤

策略模式怎么使用呢?酱紫实现的:

  1. 一个接口或者抽象类,里面两个方法(一个方法用于匹配类型,一个可替换的逻辑实现方法)
  2. 不同策略的差异化实现(就是说,不同策略的实现类)
  3. 具体上下文context来使用策略模式

举例如下

  1. 一个接口,两个方法
    public interface IFileStrategy {
        
        //属于哪种文件解析类型
        FileTypeResolveEnum gainFileType();
        
        //封装的公用算法(具体的解析方法)
        void resolve(Object objectparam);
    }
  2. 不同策略的差异化实现 
//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));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值