策略模式的使用
简介:策略模式主要是指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。
下面我刚做需求,根据不同的交易类型发送不同的通知给商户。
需求:扫描商户订单给商户发送通知,不同的交易类型,有不同通知报文。
比如:TX(提现),CZ(充值)
重构前的代码:
if(order.getTp().eqults("TX")){
//发送提现通知
}else if(order.getTp().eqults("CZ")){
//发送充值通知
}else if ....
重构前很多if,else,假如再增加一个交易类型,那么又需要新增一个if,很明显违背了"开闭原则",即对新增开放,对修改关闭。重构前整个通知系统有10多种通知,而且以后可能持续增加,开发维护都越来越困难。
重构:
首先观察一下,这段共同的行为是发送通知,但是不同的业务,有不同的发送报文。将组发送报文的代码抽象出来,刚好用得上策略模式。
参数策略接口
/**
* 发关参数策略接口
*/
public interface IPostParamStrategy {
PostParamData genParam(TAccountTxnLog tAccountTxnLog)
}
提现参数策略
/**
* 提现参数策略
*/
public class CashoutPostParamStrategy implements IPostParamStrategy {
@Override
public PostParamData genParam(TAccountTxnLog tAccountTxnLog) throws FuiouException {
PostParamData resData = new PostParamData();
resData.setPostJson(genJson(tAccountTxnLog));//设置提现post报文
resData.setPostUrl(getTxUrl());//设置提现通知地址
return resData;
}
}
充值参数策略
/**
* 充值参数策略
*/
public class RechargePostParamStrategy implements IPostParamStrategy {
@Override
public PostParamData genParam(TAccountTxnLog tAccountTxnLog) throws FuiouException {
PostParamData resData = new PostParamData();
resData.setPostJson(genJson(tAccountTxnLog));//设置充值具体post报文
resData.setPostUrl(getCzUrl());//设置充值通知地址
return resData;
}
}
策略环境(策略的调用)
/**
* 策略环境(策略的调用)
*/
public class PostParamContext {
private static Map<String, IPostParamStrategy> paramStrategyMap;
public static IPostParamStrategy getStrategy(String urlTp) throws FuiouException {
for (String key : paramMapStrategy.keySet()) {
if (urlTp.equals(key)) {
return paramMapStrategy.get(key);
}
}
throw new FuiouException("未找该通知类型,请确认请求参数urlTp");
}
public void setParamStrategyMap(Map<String, IPostParamStrategy> paramStrategyMap) {
PostParamGenGenerator.paramStrategyMap = paramStrategyMap;
}
}
主程序
//主程序
List<TAccountTxnLog> txnLogs = TAccountTxnLogMapper.listUnNotifyData();
for(TAccountTxnLog txnData : txnLogs){
//获取通知参数
PostParamData paramData = PostParamContext.getStrategy(txnData.getBusiTp()).genParamStrategy(txnData);
HttpClint.post(paramData.getPostUrl(),paramData.getPostJson());
}
post参数生成器中PostParamGenGenerator的paramMap用spring注入
<bean class="com.fuiou.jzh.notify.core.assembler.PostParamContext">
<property name="paramStrategyMap">
<map>
<entry key="CZ" value-ref="rechargePostParamStrategy" />
<entry key="TX" value-ref="cashoutPostParamStrategy" />
</map>
</property>
总结:
重构后,如果再加一个通知类型,只需要新增一个类,实现IPostParamStrategy接口,另外配置文件上加一个类型就可以了,开发效率大大提高,代码也非常简洁,并且新的通知类型即使代码有问题,也完全不会影响老的业务通知。