策略模式实现多种支付方式
使用策略模式优雅的实现多种支付方式(支付宝、微信),或者多种支付场景(订单、维修金)的业务,且方便扩展。
下例是使用注解配合反射方式,扫描到所有的具体的支付策略并放到map集合中,然后根据前端传递来的支付类型参数,选择对应的支付策略,完成支付过程。
如上图:
PayStrategy是支付策略接口;
OrderPay(订单支付),RepairPay(维修金支付)是具体的支付策略(支付场景);
AbstractPayService是实现PayStrategy接口的抽象类,规定了支付的流程,在其中选择具体的支付策略,为controller提供支付接口;
PayServiceImpl实现AbstractPayService中规定的支付流程的具体步骤,通过PayStrategyFactory获取实际的支付策略class,通过BeansUtil返回spring容器中的策略实现类bean;
PayStrategyFactory通过扫描被Pay注解注释的类,获得所有支付策略的类型和class;
Pay注解表名被注解的类是一个具体的支付策略,可以设置支付类型。
具体代码如下:
PayStrategy
package com.zhya.strategy.service; /** * 支付策略 * * @author zhangyang * @date 2018/11/14 **/ public interface PayStrategy { /** * 支付前准备支付参数 * * @param payFor * @return */ boolean prePay(String payFor); /** * 支付后处理支付回调结果 * * @param payFor * @param isPaySuccess */ void afterPay(String payFor, boolean isPaySuccess); }
Pay注解
package com.zhya.strategy.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 支付策略 * * @author zhangyang * @date 2018/11/14 **/ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Pay { /** * 支付类型 * * @return */ String value(); }
OrderPay订单支付
package com.zhya.strategy.service.impl; import com.zhya.strategy.annotation.Pay; import com.zhya.strategy.service.PayStrategy; import org.springframework.stereotype.Service; /** * 订单支付 * * @author zhangyang * @date 2018/11/14 **/ @Service @Pay("order") public class OrderPay implements PayStrategy { /** * 支付前准备支付参数 * * @param payFor */ @Override public boolean prePay(String payFor) { System.out.printf("-----------%s-----------\r\n", "订单支付"); return true; } /** * 支付后处理支付回调结果 * * @param payFor * @param isPaySuccess */ @Override public void afterPay(String payFor, boolean isPaySuccess) { System.out.printf("-----------%s-----------\n", "订单支付回调"); } }
RepairPay维修金支付
package com.zhya.strategy.service.impl; import com.zhya.strategy.annotation.Pay; import com.zhya.strategy.service.PayStrategy; import org.springframework.stereotype.Service; /** * 维修金支付 * * @author zhangyang * @date 2018/11/14 **/ @Service @Pay("repair") public class RepairPay implements PayStrategy { /** * 支付前准备支付参数 * * @param payFor */ @Override public boolean prePay(String payFor) { System.out.printf("-----------%s-----------\r\n", "维修金支付"); return true; } /** * 支付后处理支付回调结果 * * @param payFor * @param isPaySuccess */ @Override public void afterPay(String payFor, boolean isPaySuccess) { System.out.printf("-----------%s-----------\r\n", "维修金支付回调"); } }
BeansUtil
package com.zhya.strategy.util; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * bean工具类 * * @author zhangyang * @date 2018/11/14 **/ @Component public class BeansUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { BeansUtil.applicationContext = applicationContext; } /** * 获取实例 * * @param clazz * @return */ public static Object getBean(Class clazz) { return applicationContext.getBean(clazz); } }
PayStrategyFactory策略工厂
package com.zhya.strategy.util; import com.zhya.strategy.annotation.Pay; import com.zhya.strategy.service.PayStrategy; import org.reflections.Reflections; import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * 支付策略工厂 * * @author zhangyang * @date 2018/11/14 **/ public class PayStrategyFactory { // 单例开始 /** * 私有化构造函数,单例 */ private PayStrategyFactory() { } private static class Builder { private static final PayStrategyFactory payStrategyFactory = new PayStrategyFactory(); } public static PayStrategyFactory getInstance() { return Builder.payStrategyFactory; } // 单例结束 private static final String PAY_STRATEGY_IMPLEMENTATION_PACKAGE = "com.zhya.strategy.service.impl"; private static final Map<String, Class> STRATEGY_MAP = new HashMap<>(); // 获取所有支付策略 static { Reflections reflections = new Reflections(PAY_STRATEGY_IMPLEMENTATION_PACKAGE); Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Pay.class); classSet.forEach(aClass -> { Pay payAnnotation = aClass.getAnnotation(Pay.class); STRATEGY_MAP.put(payAnnotation.value(), aClass); }); } /** * 根据支付策略类型获取支付策略bean * * @param type * @return */ public static PayStrategy getStrategy(String type) { // 反射获取支付策略实现类clazz Class clazz = STRATEGY_MAP.get(type); if (StringUtils.isEmpty(clazz)) { return null; } // 通过applicationContext获取bean return (PayStrategy) BeansUtil.getBean(clazz); } }
AbstractPayService提供支付服务的抽象类
package com.zhya.strategy.service; /** * 支付service * * @author zhangyang * @date 2018/11/14 **/ public abstract class AbstractPayService implements PayStrategy { protected String payType; /** * 支付 * * @param payType * @param payFor */ public void pay(String payType, String payFor) { this.payType = payType; boolean isPrepared = prePay(payFor); if (isPrepared) { System.out.println("------------支付请求已提交------------"); } else { System.out.println("------------支付请求提交失败------------"); return; } afterPay(payFor, true); } }
PayServiceImpl支付服务实现类
package com.zhya.strategy.service.impl; import com.zhya.strategy.service.AbstractPayService; import com.zhya.strategy.service.PayStrategy; import com.zhya.strategy.util.PayStrategyFactory; import org.springframework.stereotype.Service; /** * 支付service * * @author zhangyang * @date 2018/11/14 **/ @Service public class PayServiceImpl extends AbstractPayService { /** * 支付前准备支付参数 * * @param payFor */ @Override public boolean prePay(String payFor) { PayStrategy payStrategy = PayStrategyFactory.getStrategy(this.payType); if (payStrategy == null) { System.out.printf("没有%s类型的支付策略...\r\n", this.payType); return false; } return payStrategy.prePay(payFor); } /** * 支付后处理支付回调结果 * * @param payFor * @param isPaySuccess */ @Override public void afterPay(String payFor, boolean isPaySuccess) { PayStrategy payStrategy = PayStrategyFactory.getStrategy(this.payType); payStrategy.afterPay(payFor, true); } }
PayController
package com.zhya.strategy.controller; import com.zhya.strategy.service.AbstractPayService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * 支付 * * @author zhangyang * @date 2018/11/14 **/ @RestController @RequestMapping("pay") public class PayController { @Autowired private AbstractPayService payService; @GetMapping public void pay(@RequestParam String payType, @RequestParam String payFor) { payService.pay(payType, payFor); } }