1.訂單控制器,提供一個根據商品id和銀行渠道id計算商品折後價格的接口:java
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; @RestController @RequestMapping("/order") public class OrderController { /** * 根據商品id和銀行渠道id計算折扣後的金額 * * @param goodsId 商品id * @param channelId 銀行渠道id * @return */ @GetMapping("/calc") @ResponseBody public String calcAmount(Integer goodsId, Integer channelId) { Context context = new Context(); BigDecimal bigDecimal; try { bigDecimal = context.calRecharge(goodsId, channelId); } catch (Exception e) { e.printStackTrace(); return ""; } return bigDecimal.setScale(2) + ""; } }
2.上下文:web
import java.math.BigDecimal; public class Context { /** * 根據商品id和銀行渠道id計算折扣後的金額 * * @param goodsId 商品id * @param channelId 銀行渠道id * @return * @throws Exception */ public BigDecimal calRecharge(Integer goodsId, Integer channelId) throws Exception { StrategyFactory strategyFactory = StrategyFactory.getInstance(); // 根據渠道id查詢具體的銀行實現類 Strategy strategy = strategyFactory.create(channelId); // 調用具體的實現類進行計算 return strategy.calRecharge(goodsId, channelId); } }
3.折扣計算單例工廠類,內部用一個Map來存儲銀行渠道id和具體銀行實現類之間的映射關係,方便根據渠道id反射獲取對應銀行具體的實現類:spring
import org.reflections.Reflections; import java.util.HashMap; import java.util.Set; public class StrategyFactory { private static StrategyFactory strategyFactory = new StrategyFactory(); private StrategyFactory() { } public static StrategyFactory getInstance() { return strategyFactory; } private static HashMap<Integer, String> source_map = new HashMap<>(); static { Reflections reflections = new Reflections("ICBCBankImpl"); Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Pay.class); for (Class<?> clazz : classSet) { Pay pay = clazz.getAnnotation(Pay.class); source_map.put(pay.channelId(), clazz.getCanonicalName()); } } /** * 根據銀行渠道id從Map中獲取具體的銀行實現類 * * @param channelId * @return * @throws Exception */ public Strategy create(int channelId) throws Exception { String clazz = source_map.get(channelId); Class<?> clazz_ = Class.forName(clazz); return (Strategy) clazz_.newInstance(); } }
4.計算折後價格的接口:數據庫
import java.math.BigDecimal; public interface Strategy { BigDecimal calRecharge(Integer goodsId, Integer channelId); }
5.工商銀行實現類,類上加上@Pay註解指定工商銀行對應的數據庫中的渠道id:app
import javax.annotation.Resource; import java.math.BigDecimal; /** * 工商銀行實現類,對應的數據庫中的渠道id爲1 */ @Pay(channelId = 1) public class ICBCBankImpl implements Strategy { @Resource private GoodsMapper goodsMapper; @Resource private ChannelMapper channelMapper; /** * 根據商品id和銀行渠道id計算優惠後的價格 * * @param goodsId 商品id * @param channelId 銀行渠道id * @return */ @Override public BigDecimal calRecharge(Integer goodsId, Integer channelId) { BigDecimal goodsPrice = goodsMapper.getGoodsPriceById(goodsId); BigDecimal discountPrice = channelMapper.getDiscountPriceById(channelId); if (goodsPrice == null || discountPrice == null) { return null; } return goodsPrice.multiply(discountPrice); } }
6.用於標記銀行實現類的註解,定義了一個銀行渠道id屬性:ide
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 channelId(); }
7.模擬查詢商品價格的Dao:spa
import java.math.BigDecimal; public class GoodsMapper { public BigDecimal getGoodsPriceById(Integer goodsId) { return BigDecimal.valueOf(599); } }
8.模擬查詢查詢渠道優惠折扣的Dao:code
import java.math.BigDecimal; public class ChannelMapper { public BigDecimal getDiscountPriceById(Integer channelId) { return BigDecimal.valueOf(0.5); } }