優點:
未使用if else,就算以后增加支付類型,也不用改動之前代碼
只需要新寫一個支付類,給添加自定義注解@Pay
首先:
定義自定義注解 Pay
定義 CMBPay ICBCPay 兩種支付 根據注解中的value 標識是哪種支付(1為CMBPay 2為ICBCPay)
兩種支付都需繼承InitNewService.java 避免注入對象報錯
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); } }
項目結構:
源碼地址: https://github.com/youxiu326/sb_code