业务场景
最近碰到个需求需要实现多种不一样的第三方支付,目前是支付宝微信,像这种支付一般在系统中的流程不会变只是要对接不同的支付api。要是按常规的做法写的话一般都是用switch根据前端传的type选择不同的支付service,例如
//这边是随便写的代码,项目实际代码就不展示了,大概意思展示一下
/**
* type 支付类型 wx:微信 zfb:支付宝
* paramsVo中含有支付相关的参数
**/
public void payMethod(ParamsVo paramsVo){
PayResultVo result;
switch(paramsVo.getType()){
case "wx":
result = wxPay(paramsVo)
break;
case "zfb":
result = zfbPay(paramsVo);
break;
}
//这边获取支付结果判断结果是否支付完成
if("200".equals(result.getStatus())){
//支付完成以后做的事
}
}
设计想法和实现
使用这种写法未来要是扩展一个支付方式的话,就要修改这个switch判断里面的内容,往里面添加一个分支,这样是有违背开闭原则,而且未来要是支付方式越来越多代码看上去也不美观。所以为了未来的扩展性和代码的美观,决定用策略模式改造这块代码,利用一个接口和多个实现类来实现动态切换不同的支付方法,代码如下:
1、首先先写个接口,限制实现类的方法
public interface PayService{
public PayResultVo payFun(ParamsVo params);
}
2、写两个实现类去实现PayService接口
//wx支付
@Service
public class WxPayServiceImpl implements PayService{
public PayResultVo payFun(ParamsVo params){
System.out.print("这边写微信支付的逻辑");
//支付成功后返回统一封装的结果
return new PayResultVo();
}
}
//zfb支付
@Service
public class ZfbPayServiceImpl implements PayService{
public PayResultVo payFun(ParamsVo params){
System.out.print("这边写支付宝支付的逻辑");
//支付成功后返回统一封装的结果
return new PayResultVo();
}
}
3、写一个策略模式的调度类,这边用springboot,根据bean创建的生命周期我们可以这样写
@Component
public class PayContext implements ApplicationContextAware, InitializingBean{
//创建一个用来存放多个实现类的Map
private final Map<String,PayService> beanMap = new ConcurrentHashMap<>();
//spring 上下文,之后可以用来获取spring的bean
private ApplicationContext applicationContext;
private final static String COMM_STR = "PayServiceImpl";
@Override
public void afterPropertiesSet() throws Exception {
//将所有的支付方式实现类注入到map中方便提取使用
applicationContext.getBeansOfType(PayService.class).forEach((k,v)->{
beanMap.put(k.toLowerCase(),v);
});
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public PayResultVo payFun(ParamsVo params) {
String key = params.getType();
key = key+COMM_STR;
return beanMap.get(key.toLowerCase()).payFun(params);
}
}
4、在原来的代码中使用
//这边是随便写的代码,项目实际代码就不展示了,大概意思展示一下
/**
* type 支付类型 wx:微信 zfb:支付宝
* paramsVo中含有支付相关的参数
**/
@Autowired
private PayContext payContext;
public void payMethod(ParamsVo paramsVo){
/*switch(paramsVo.getType()){
case "wx":
result = wxPay(paramsVo)
break;
case "zfb":
result = zfbPay(paramsVo);
break;
}*/
//上面代码改造成这样,这样未来要扩展支付方法的话不用修改这块的代码只要扩展实现类就可以轻松实现扩展支付方式
PayResultVo result = payContext.payFun(paramsVo);
//这边获取支付结果判断结果是否支付完成
if("200".equals(result.getStatus())){
//支付完成以后做的事
}
}
这样就改造完了,改造完后的代码之后要扩展或者减少支付方式的话就不用修改原来的支付方法,只要创建新的支付方式实现类就能轻松实现扩展支付方式,代码入侵小
参考文章
https://blog.youkuaiyun.com/u014508939/article/details/121612924