「这是我参与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类中的代码做改动。好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊