優勢:java
未使用if else,就算之後增長支付類型,也不用改動以前代碼git
只須要新寫一個支付類,給添加自定義註解@Paygithub
首先:web
定義自定義註解 Payspring
定義 CMBPay ICBCPay 兩種支付 根據註解中的value 標識是哪一種支付(1爲CMBPay 2爲ICBCPay)編程
兩種支付都需繼承InitNewService.java 避免注入對象報錯ide
package com.huarui.inter; import java.math.BigDecimal; /** * 支付需實現該接口 * 接口編程: */ public interface Strategy { /** * 計算支付金額 經過渠道id和商品id 進行價格計算 * @param channelId * @param goodsId * @return */ BigDecimal calRecharge(Integer channelId,Integer goodsId); }
package com.huarui.pay; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) //註解定義到類上 @Retention(RetentionPolicy.RUNTIME) //生命週期 public @interface Pay { int value(); }
@Pay(2) public class ICBCPay extends InitNewService implements Strategy { @Override public BigDecimal calRecharge(Integer channelId, Integer goodsId) { //經過渠道id查詢優惠折扣 //經過商品id查詢商品價格 //返回商品最終價格 return new BigDecimal(100); } }
package com.huarui.pay; import com.huarui.inter.Strategy; import com.huarui.util.CommonUtil; import com.huarui.util.InitNewService; import org.springframework.beans.factory.annotation.Autowired; import java.math.BigDecimal; @Pay(1) public class CMBPay extends InitNewService implements Strategy { @Autowired private CommonUtil commonUtil; @Override public BigDecimal calRecharge(Integer channelId, Integer goodsId) { //經過渠道id查詢優惠折扣 //經過商品id查詢商品價格 System.out.println(commonUtil.injectStr()); //返回商品最終價格 return new BigDecimal(100); } }
package com.huarui.factory; import com.huarui.inter.Strategy; import com.huarui.pay.Pay; import org.reflections.Reflections; import java.util.HashMap; import java.util.Set; /** * 【工廠類】 * 經過指定掃碼路徑讀取帶有自定義註解Pay的類 * <br>並將全類名保存至map中,格式爲["pay的value":"類的全類名"] * <br> 定義了creator方法,傳入支付類型 返回 指定支付對象 */ public class StrategyFactory { private static StrategyFactory factory = new StrategyFactory(); /** * 單例 * @return */ public static StrategyFactory getInstance(){ return factory; } public static HashMap<Integer,String> sourceMap = new HashMap<>(); static { //反射工具包,指明掃描路徑 Reflections reflections = new Reflections("com.huarui.pay"); //獲取帶咱們pay註解的類 Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Pay.class); //根據註解的值,將全類名放到map中 for (Class clazz : classSet){ Pay pay = (Pay) clazz.getAnnotation(Pay.class); sourceMap.put(pay.value(),clazz.getCanonicalName()); } } public Strategy creator(int type) throws Exception { //取得全類名 String className = sourceMap.get(type); //取得類對象 Class clazz= Class.forName(className); //反射建立對象 return (Strategy) clazz.newInstance(); } }
package com.huarui.inter; import com.huarui.factory.StrategyFactory; import java.math.BigDecimal; public class Context { /** * * @param channelId 支付類型id * @param goodsId 商品id * @return * @throws Exception */ public BigDecimal calRecharge(Integer channelId,Integer goodsId) throws Exception { Strategy strategy = StrategyFactory.getInstance().creator(channelId); return strategy.calRecharge(channelId,goodsId); } }
junit測試類工具
package com.huarui; import com.huarui.inter.Context; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.autoconfigure.web.ResourceProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.math.BigDecimal; @RunWith(SpringRunner.class) @SpringBootTest public class SbCodeApplicationTests { @Test public void contextLoads() throws Exception { Context context = new Context(); BigDecimal bigDecimal = context.calRecharge(1,500); System.out.println(bigDecimal); } }
項目結構:測試