使用策略模式優雅的實現多種支付方式(支付寶、微信),或者多種支付場景(訂單、維修金)的業務,且方便擴展。
下例是使用注解配合反射方式,掃描到所有的具體的支付策略並放到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); } }