当前位置: 首页 > news >正文

SpringBoot 模板模式实现优惠券逻辑

一、计算逻辑的类结构图

 在这张图里,顶层接口 RuleTemplate 定义了 calculate 方法,抽象模板类 AbstractRuleTemplate 将通用的模板计算逻辑在 calculate 方法中实现,同时它还定义了一个抽象方法 calculateNewPrice 作为子类的扩展点。各个具体的优惠计算类通过继承 AbstractRuleTemplate,并实现 calculateNewPrice 来编写自己的优惠计算方式。

二、代码实现

1、RuleTemplate.java

public interface RuleTemplate {// 计算优惠券ShoppingCart calculate(ShoppingCart settlement);
}

2、AbstractRuleTemplate.java

public ShoppingCart calculate(ShoppingCart order) {// 获取订单总价Long orderTotalAmount = getTotalPrice(order.getProducts());// 获取以shopId为维度的总价统计Map<Long, Long> sumAmount = getTotalPriceGroupByShop(order.getProducts());CouponTemplateInfo template = order.getCouponInfos().get(0).getTemplate();// 最低消费限制Long threshold = template.getRule().getDiscount().getThreshold();// 优惠金额或者打折比例Long quota = template.getRule().getDiscount().getQuota();// 如果优惠券未指定shopId,则shopTotalAmount=orderTotalAmount// 如果指定了shopId,则shopTotalAmount=对应门店下商品总价Long shopId = template.getShopId();Long shopTotalAmount = (shopId == null) ? orderTotalAmount : sumAmount.get(shopId);// 如果不符合优惠券使用标准, 则直接按原价走,不使用优惠券if (shopTotalAmount == null || shopTotalAmount < threshold) {log.debug("Totals of amount not meet");order.setCost(orderTotalAmount);order.setCouponInfos(Collections.emptyList());return order;}// 子类中实现calculateNewPrice计算新的价格Long newCost = calculateNewPrice(orderTotalAmount, shopTotalAmount, quota);if (newCost < minCost()) {newCost = minCost();}order.setCost(newCost);log.debug("original price={}, new price={}", orderTotalAmount, newCost);return order;
}

3、子类

MoneyOffTemplate.java

@Slf4j
@Component
public class MoneyOffTemplate extends AbstractRuleTemplate implements RuleTemplate {@Overrideprotected Long calculateNewPrice(Long totalAmount, Long shopAmount, Long quota) {// benefitAmount是扣减的价格// 如果当前门店的商品总价<quota,那么最多只能扣减shopAmount的钱数Long benefitAmount = shopAmount < quota ? shopAmount : quota;return totalAmount - benefitAmount;}    
}

4、工厂类

CouponTemplateFactory.java

@Component
@Slf4j
public class CouponTemplateFactory {@Autowiredprivate MoneyOffTemplate moneyOffTemplate;@Autowiredprivate DiscountTemplate discountTemplate;@Autowiredprivate RandomReductionTemplate randomReductionTemplate;@Autowiredprivate LonelyNightTemplate lonelyNightTemplate;@Autowiredprivate DummyTemplate dummyTemplate;@Autowiredprivate AntiPauTemplate antiPauTemplate;public RuleTemplate getTemplate(ShoppingCart order) {// 不使用优惠券if (CollectionUtils.isEmpty(order.getCouponInfos())) {// dummy模板直接返回原价,不进行优惠计算return dummyTemplate;}// 获取优惠券的类别// 目前每个订单只支持单张优惠券CouponTemplateInfo template = order.getCouponInfos().get(0).getTemplate();CouponType category = CouponType.convert(template.getType());switch (category) {// 订单满减券case MONEY_OFF:return moneyOffTemplate;// 随机立减券case RANDOM_DISCOUNT:return randomReductionTemplate;// 午夜下单优惠翻倍case LONELY_NIGHT_MONEY_OFF:return lonelyNightTemplate;// 打折券case DISCOUNT:return discountTemplate;case ANTI_PUA:return antiPauTemplate;// 未知类型的券模板default:return dummyTemplate;}}}

5、使用

CouponCalculationServiceImpl.java

    @Autowiredprivate CouponTemplateFactory couponProcessorFactory;// 优惠券结算// 这里通过Factory类决定使用哪个底层Rule,底层规则对上层透明@Overridepublic ShoppingCart calculateOrderPrice(@RequestBody ShoppingCart cart) {log.info("calculate order price: {}", JSON.toJSONString(cart));RuleTemplate ruleTemplate = couponProcessorFactory.getTemplate(cart);return ruleTemplate.calculate(cart);}

http://www.lryc.cn/news/134116.html

相关文章:

  • 并查集 rank 的优化(Java 实例代码)
  • TDA4超级玩家浮出水面,行泊一体功能、成本刷到极致
  • 3分钟了解Android中稳定性测试
  • LVS-DR+keepalived实现高可用负载群集
  • 阿里云国际版注册教程
  • 基于百度文心大模型创作的实践与谈论
  • Java基础知识题(五)
  • 攻防世界-fileinclude
  • 流媒体服务器SRS的搭建及QT下RTMP推流客户端的编写
  • Effective C++条款11——在operator=中处理“自我赋值”(构造/析构/赋值运算)
  • 可视化绘图技巧100篇基础篇(八)-气泡图(一)
  • Elasticsearch查询之Disjunction Max Query
  • Lock wait timeout exceeded; try restarting transaction的错误
  • ShardingSphere01-docker环境安装
  • Java代码审计13之URLDNS链
  • 区间预测 | MATLAB实现QRBiGRU双向门控循环单元分位数回归时间序列区间预测
  • Python面向对象植物大战僵尸
  • 大屏模板,增加自适应(包含websocket)
  • 电商系统架构设计系列(九):如何规划和设计分库分表?
  • 从Web 2.0到Web 3.0,互联网有哪些变革?
  • QT中资源文件resourcefile的使用,使用API完成页面布局
  • 2337. 移动片段得到字符串
  • Java并发编程第5讲——volatile关键字(万字详解)
  • 6.小程序api分类
  • 什么是PPS和TOD时序?授时防护设备是什么?
  • 推荐一款好用的开源视频播放器(免费无广告)
  • STM32 CubeMX (第三步Freertos中断管理和软件定时)
  • Java虚拟机(JVM):堆溢出
  • C语言,Linux,静态库编写方法,makefile与shell脚本的关系。
  • Php“牵手”淘宝商品详情页数据采集方法,淘宝API接口申请指南