设计模式的应用(工厂+策略模式去除多余if...else)

1,105 阅读3分钟

「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战

1、前言

记得刚开始在大学的时候,刚接触Java EE的开发,跟着老师做完一个教学管理系统就觉着很厉害了。后来,毕业后入职的第一家公司,每天都在很忙的做着CRUD的工作,完全是“面向过程”编程,一股脑地写完代码,完成功能。慢慢也意识到代码质量的重要性,特别是设计模式的应用。(PS:面试时,这块的内容也是必问,但之前知识背过面试题,很少去实际用起来)下面,就结和我在实际开发中遇到的问题为大家分享下如何使用设计模式,让代码变得更“优雅”。

2、工厂+策略模式取代多余的if...else

问题是这样的,在银行的交易系统中,对每一类交易的有金额限制,以及交易情况的分析。这里面就需要我们将每一类交易的原始数据处理成预定格式。每一类交易的原始数据格式不同,就需要分类处理。刚开始,我就基于原始交易数据的交易类型来判断,就会写很多if...else if...else if,后面被告知还可能有更多的交易类型。这个时候,代码已经很臃肿了,我就开始思考去除多余if..else if,而工厂+策略模式就可以很好的处理这种情况。

策略模式:一个类的行为或其算法可以在运行时更改。刚读完这句话,我也不是很理解。这里我举一个例子:比如,我去上班时,可以选择坐公交,也可以中途下车骑自行车去,那么每一种上班方式就是一种策略。

下面我们结合代码来介绍下,具体使用:

//未修改前
//头寸-拆分外汇交易
public void splitFXTrade(FXTradeEntity fxTrade, Map<String, String> brieflyPostionInfo) throws Exception {
    String tradeType = fxTrade.getTradeType();
    switch (tradeType) {
        case FXSPOT:
        case PMSPOT:
            splitFXSpotTradeComponent.dealFXSpotTradeSplit(fxTrade, brieflyPostionInfo);
            break;
        case FXFWD:
        case PMFWD:
            splitFXFWDTradeComponent.dealFXFWDTradeSplit(fxTrade, brieflyPostionInfo);
            break;
        case FXSWAP:
        case PMSWAP:
            splitFXSwapTradeComponent.dealFXSwapTradeSplit(fxTrade, brieflyPostionInfo);
            break;
        default:
            log.info("不支持的交易类型:" + tradeType);
    }
}

使用策略模式:

//定义策略接口 这里继承InitializingBean类是为了将具体的实现类,在项目启动时就注册到策略工厂内
public interface SplitTradeHandler extends InitializingBean {
    
    SplitFXTrade splitFXTrade(FXTrade fxTrade);
    
}
​
//实现类、处理某一类交易的拆分 
@Component
public class FXFwdSplitTradeHandler implements SplitTradeHandler {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(FXFwdSplitTradeHandler.class);
​
    @Autowired
    private FXFwdSplitTradeComponent fxFwdSplitTradeComponent;
​
    //注册到策略工厂
    @Override
    public void afterPropertiesSet() throws Exception {
        SplitTradeHandlerFactory.register(TradeType.FXFWD.getTradeType(), this);
    }
​
    @Override
    public SplitFXTrade splitFXTrade(FXTrade fxTrade) {
        //do something
    }
​
}
​
//交易处理工厂类
public class SplitTradeHandlerFactory {
    
    private static Map<String, SplitTradeHandler> strategyMap = new HashMap<>(); 
​
    //根据TradeType获取对应的handler实现
    public static SplitTradeHandler getSplitTradeHandler(String fxTradeType) throws KPromptException{
        if (strategyMap.containsKey(fxTradeType)) {
            return strategyMap.get(fxTradeType);
        }
        LOGGER.error("未针对当前交易类型,做实现,交易类型:{}", fxTradeType);
        throw new KPromptException("未针对当前交易类型,做实现,交易类型:" + fxTradeType);
    }
​
    /**
     * @Title       register
     * @Description 注册到strategyMap
     * @param       @param fxTradeType
     * @param       @param handler(参数说明)
     * @return      void(返回类型)
     */
    public static void register(String fxTradeType, SplitTradeHandler handler){
        if(StringUtils.isEmpty(fxTradeType) || null == handler){
            return;
        }
        strategyMap.put(fxTradeType, handler);
    }
    
}
​
//service类
//对外提供交易数据处理服务
@Service
public class SplitTradeService {
    
    //处理交易数据
    public SplitFXTrade splitFXTrade(FXTrade fxTrade) throws KPromptException {
        return SplitTradeHandlerFactory.getSplitTradeHandler(fxTrade.getTradetype()).splitFXTrade(fxTrade);
    }
    
}

可以看到,如果新增了一种交易类型的数据需要处理,我们只需要实现策略接口,将其注册到策略工厂内即可,不需要对service类中的代码做改动。好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊