公司最近在做聚合支付的功能,原来支付方案是不同的支付商户不同的业务处理,扩展性极差,且每新增一个业务商户都要单独开发一套支付接口,很明显这违背了OOP的思想。
策略模式的组成部分有三部分

环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。 具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法。
支付方式的组成也有三部分

支付策略接口(PayStrategy):定义支付方式
具体支付方式(H5PayStrategy、WxPayStrategy、根据自己的):具体的支付算法
支付策略上下文(PayStrategyContent):管理所有支付方式的引用,并根据用户选择引用对应的支付方式。
代码实现(本案例是接的银联支付)
   支付策略接口(PayStrategy)

/**
*@program:traffic-resource
*@description支付策略接口
*@author:belive
*@create:2020-12-2521:06
**/
public interface PayStrategy{
/**
*支付接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@param param
*@returnStringjson字符串
*/
RestRes<String>consumeApply(String param);

/**
*查询支付结果接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@param param
*@returnStringjson字符串
*/
RestRes<String>consumeApplyDetail(String param);

/**
*退款接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@param param
*@returnStringjson字符串
*/
RestRes<String>refund(String param);

/**
*查询退款结果接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@param param
*@returnStringjson字符串
*/
RestRes<String>refundQuery(String param);

/**
*关闭订单接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@param param
*@returnStringjson字符串
*/
RestRes<String>depositApply(String param);

具体支付方式(MiniPayStrategy) 本案例就以扫码支付为例

/**
*@program:traffic-resource
*@description
*@author:belive
*@create:2020-12-2521:18
**/
@Slf4j
@Service
public class QrCodePayStrategy implements PayStrategy{

@Value("${unionPay.url.qrcode_get_qrcode}")
private String qrcode_get_qrcode;

@Override
publicRestRes<String>consumeApply(String body){
RestRes<String>restRes=newRestRes<>();
TransactionHttptransactionHttp=new TransactionHttp();
String result=transactionHttp.send("https://api-mop.chinaums.com/v1/netpay/bills/get-qrcode",body);

JSONObject resultObj=JSON.parseObject(result);
if("SUCCESS".equals(resultObj.getString("errCode"))){
restRes.setMessage("获取支付链接成功");
restRes.setCode(0);
}else{
restRes.setMessage("获取支付链接失败");
restRes.setCode(1000);
}
restRes.setData(result);
Return restRes;
}

@Override
public RestRes<String>consumeApplyDetail(String param){
Return null;
}

@Override
public RestRes<String>refund(String param){
return null;
}

@Override
public RestRes<String>refundQuery(String param){
Return null;
}

@Override
public RestRes<String>depositApply(String param){
Return null;
}
}

支付策略上下文(PayStrategyContent)

/**
*@program:traffic-resource
*@description支付策略上下文
*@author:belive
*@create:2020-12-2521:19
**/
@Component
publicclassPayStrategyContent{
/**策略实例集合*/
        private ConcurrentHashMap<String,PayStrategy>strategyMap=new ConcurrentHashMap<>(20);

/**
*注入策略实例
*如果使用的是构造器注入,可能会有多个参数注入进来。
*
*如果使用的是field反射注入
*
*如果使用的是setter方法注入,那么你将不能将属性设置为final。
*
*@paramstrategyMap
*注意注入类型要是Map基础类型
*/
@Autowired
public PayStrategyContent(Map<String,PayStrategy>strategyMap){
    //清空集合数据
    this.strategyMap.clear();
    if(!CollectionUtils.isEmpty(strategyMap)){
    strategyMap.forEach((beanName,payStrategy)->{
    if(StringUtils.isEmpty(beanName)||payStrategy==null){
    return;
    }
    this.strategyMap.put(beanName.toLowerCase(),payStrategy);
    });
    }
    }

/**
*选择支付方式
*小程序、H5、扫码
*
*@parampaymentEnums
*
*@returnRemoteResult
*/
public RestRes<String>consumeApply(PaymentEnums paymentEnums,Stringparam){
if(CollectionUtils.isEmpty(strategyMap)){
throw new ApiException(ErrorCodeEnum.UNION05);
}
return this.strategyMap.get(paymentEnums.getBeanName()).consumeApply(param);
}
/**
*查询支付结果接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@parampaymentEnums
*
*@returnRemoteResult
*/
public RestRes<String>consumeApplyDetail(PaymentEnums paymentEnums,Stringparam){
if(CollectionUtils.isEmpty(strategyMap)){
throw new ApiException(ErrorCodeEnum.UNION05);
}
return this.strategyMap.get(paymentEnums.getBeanName()).consumeApplyDetail(param);
}
/**
*退款接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@parampaymentEnums
*
*@returnRemoteResult
*/
public RestRes<String>refund(PaymentEnums paymentEnums,Stringparam){
if(CollectionUtils.isEmpty(strategyMap)){
throw new ApiException(ErrorCodeEnum.UNION05);
}
returnthis.strategyMap.get(paymentEnums.getBeanName()).refund(param);
}

/**
*查询退款结果接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@parampaymentEnums
*
*@returnRemoteResult
*/
public RestRes<String>refundQuery(PaymentEnums paymentEnums,String param){
if(CollectionUtils.isEmpty(strategyMap)){
thrownewApiException(ErrorCodeEnum.UNION05);
}
return this.strategyMap.get(paymentEnums.getBeanName()).refundQuery(param);
}

/**
*关闭订单接口
*1.小程序支付
*2.h5支付
*3.扫码支付
*4.app支付
*
*@parampaymentEnums
*
*@returnRemoteResult
*/
public RestRes<String>depositApply(PaymentEnums paymentEnums,String param){
if(CollectionUtils.isEmpty(strategyMap)){
throw new ApiException(ErrorCodeEnum.UNION05);
}
return this.strategyMap.get(paymentEnums.getBeanName()).depositApply(param);
}

支付方式枚举(PaymentEnums)

    /**
*@program:traffic-resource
*支付方式枚举对象
*code->支付方式别名
*beanName->实例的名称
*@author:belive
*@create:2020-12-2521:00
**/
public enumPaymentEnums{
/**支付方式*/
H5_PAY("H5_PAY",H5PayStrategy.class.getSimpleName()),
MINI_PAY("MINI_PAY",MiniPayStrategy.class.getSimpleName()),
QR_CODE_PAY("QR_CODE_PAY",QrCodePayStrategy.class.getSimpleName()),
;
/**
*枚举定义+描述
*/
private String code;
private String beanName;

PaymentEnums(String code,String beanName){
this.code=code;
this.beanName=StringUtils.isNotEmpty(beanName)?beanName.toLowerCase():null;
}
/**
*根据code获取对应的枚举对象
*/
public static PaymentEnums getEnum(String code){
PaymentEnums[]values=PaymentEnums.values();
if(null!=code&&values.length>0){
for(PaymentEnumsvalue:values){
if(value.code.equals(code)){
returnvalue;
}
}
}
returnnull;
}
/**
*该code在枚举列表code属性是否存在
*/
publicstaticbooleancontainsCode(Stringcode){
PaymentEnumsanEnum=getEnum(code);
returnanEnum!=null;
}
/**
*判断code与枚举中的code是否相同
*/
public static boolean equals(Stringcode,PaymentEnums calendarSourceEnum){
returncalendarSourceEnum.code.equals(code);
}

publicStringgetCode(){
returncode;
}
publicStringgetBeanName(){
returnbeanName;
}
}

自定义Bean加载(PayStrategyContentConfig)


/**
*@program: traffic-resource
*@description
*@author: belive
*@create: 2020-12-3023:07
**/
@Configuration
public class PayStrategyContentConfig {
@Bean
 public PayStrategyContent payStrategyContentInit() {
        H5PayStrategy h5PayStrategy = new H5PayStrategy();
 MiniPayStrategy miniPayStrategy = new MiniPayStrategy();
 QrCodePayStrategy qrCodePayStrategy = new QrCodePayStrategy();
 HashMap<String, PayStrategy> strategyMap = new HashMap<>();
 strategyMap.put(PaymentEnums.H5_PAY.getBeanName(), h5PayStrategy);
 strategyMap.put(PaymentEnums.MINI_PAY.getBeanName(), miniPayStrategy);
 strategyMap.put(PaymentEnums.QR_CODE_PAY.getBeanName(), qrCodePayStrategy);
 PayStrategyContent payStrategyContent = new PayStrategyContent(strategyMap);
 return payStrategyContent;
 }
}

支付相关业务调用(代码片段)

@Resource
private PayStrategyContentConfig payStrategyContentConfig;
RestRes<String>result=payStrategyContentConfig.payStrategyContentInit().consumeApply(PaymentEnums.QR_CODE_PAY,body.toJSONString());
03-05 20:33