1.订单控制器,提供一个根据商品id和银行渠道id计算商品折后价格的接口:
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.上下文:
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反射获取对应银行具体的实现类:
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:
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属性:
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:
import java.math.BigDecimal; public class GoodsMapper {
public BigDecimal getGoodsPriceById(Integer goodsId) {
return BigDecimal.valueOf(599);
}
}
8.模拟查询查询渠道优惠折扣的Dao:
import java.math.BigDecimal; public class ChannelMapper {
public BigDecimal getDiscountPriceById(Integer channelId) {
return BigDecimal.valueOf(0.5);
}
}