SpringBoot 模板模式实现优惠券逻辑的示例代码

 更新时间:2023年08月22日 14:08:57   作者:全栈技术负责人  
这篇文章主要介绍了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 {
    @Override
    protected 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 {
    @Autowired
    private MoneyOffTemplate moneyOffTemplate;
    @Autowired
    private DiscountTemplate discountTemplate;
    @Autowired
    private RandomReductionTemplate randomReductionTemplate;
    @Autowired
    private LonelyNightTemplate lonelyNightTemplate;
    @Autowired
    private DummyTemplate dummyTemplate;
    @Autowired
    private 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

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

到此这篇关于SpringBoot 模板模式实现优惠券逻辑的文章就介绍到这了,更多相关SpringBoot 优惠券逻辑内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java集合ArrayList与LinkedList详解

    Java集合ArrayList与LinkedList详解

    这篇文章主要介绍了Java集合ArrayList与LinkedList详解,对于ArrayList和LinkedList,他们都是List接口的一个实现类,并且我们知道他们的实现方式各不相同,例如ArrayList底层实现是一个数组
    2022-08-08
  • Java中使用StackWalker和Stream API进行堆栈遍历

    Java中使用StackWalker和Stream API进行堆栈遍历

    StackWalking API是添加到Java中最酷的(并且对大多数开发人员来说完全不切实际,一般不会用,除非深层跟踪调优)的功能之一。在这篇简短的文章中,我们将看到它是什么以及使用它有多么容易,很快的认识它
    2018-09-09
  • Java实现拓扑排序的示例代码

    Java实现拓扑排序的示例代码

    这篇文章我们要讲的是拓扑排序,这是一个针对有向无环图的算法,主要是为了解决前驱后继的关系,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-05-05
  • Intellij IDEA 2017.3使用Lombok及常用注解介绍

    Intellij IDEA 2017.3使用Lombok及常用注解介绍

    这篇文章主要介绍了Intellij IDEA 2017.3使用Lombok及常用注解介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Mybatis示例之SelectKey的应用

    Mybatis示例之SelectKey的应用

    今天小编就为大家分享一篇关于Mybatis示例之SelectKey的应用,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • SpringMVC中DispatcherServlet的HandlerMapping详解

    SpringMVC中DispatcherServlet的HandlerMapping详解

    这篇文章主要介绍了SpringMVC中DispatcherServlet的HandlerMapping详解,上回说的Handler,我们说是处理特定请求的,也就是说,不是所有的请求都能处理,那么问题来了,我们怎知道哪个请求是由哪个Handler处理的呢,需要的朋友可以参考下
    2023-10-10
  • java中使用url进行编码和解码

    java中使用url进行编码和解码

    这篇文章主要介绍了java中使用url进行编码和解码,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • java控制台实现学生信息管理系统(集合版)

    java控制台实现学生信息管理系统(集合版)

    这篇文章主要为大家详细介绍了java控制台实现学生信息管理系统的集合版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • Spring单元测试类ApplicationTests错误的解决

    Spring单元测试类ApplicationTests错误的解决

    这篇文章主要介绍了Spring单元测试类ApplicationTests错误的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java 中的io模型详解

    Java 中的io模型详解

    这篇文章主要介绍了Java 中io模型的相关资料,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-04-04

最新评论