SpringBoot?模板模式實(shí)現(xiàn)優(yōu)惠券邏輯的示例代碼
一、計(jì)算邏輯的類結(jié)構(gòu)圖
在這張圖里,頂層接口 RuleTemplate 定義了 calculate 方法,抽象模板類 AbstractRuleTemplate 將通用的模板計(jì)算邏輯在 calculate 方法中實(shí)現(xiàn),同時(shí)它還定義了一個(gè)抽象方法 calculateNewPrice 作為子類的擴(kuò)展點(diǎn)。各個(gè)具體的優(yōu)惠計(jì)算類通過繼承 AbstractRuleTemplate,并實(shí)現(xiàn) calculateNewPrice 來編寫自己的優(yōu)惠計(jì)算方式。
二、代碼實(shí)現(xiàn)
1、RuleTemplate.java
public interface RuleTemplate { // 計(jì)算優(yōu)惠券 ShoppingCart calculate(ShoppingCart settlement); }
2、AbstractRuleTemplate.java
public ShoppingCart calculate(ShoppingCart order) { // 獲取訂單總價(jià) Long orderTotalAmount = getTotalPrice(order.getProducts()); // 獲取以shopId為維度的總價(jià)統(tǒng)計(jì) Map<Long, Long> sumAmount = getTotalPriceGroupByShop(order.getProducts()); CouponTemplateInfo template = order.getCouponInfos().get(0).getTemplate(); // 最低消費(fèi)限制 Long threshold = template.getRule().getDiscount().getThreshold(); // 優(yōu)惠金額或者打折比例 Long quota = template.getRule().getDiscount().getQuota(); // 如果優(yōu)惠券未指定shopId,則shopTotalAmount=orderTotalAmount // 如果指定了shopId,則shopTotalAmount=對(duì)應(yīng)門店下商品總價(jià) Long shopId = template.getShopId(); Long shopTotalAmount = (shopId == null) ? orderTotalAmount : sumAmount.get(shopId); // 如果不符合優(yōu)惠券使用標(biāo)準(zhǔn), 則直接按原價(jià)走,不使用優(yōu)惠券 if (shopTotalAmount == null || shopTotalAmount < threshold) { log.debug("Totals of amount not meet"); order.setCost(orderTotalAmount); order.setCouponInfos(Collections.emptyList()); return order; } // 子類中實(shí)現(xiàn)calculateNewPrice計(jì)算新的價(jià)格 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是扣減的價(jià)格 // 如果當(dāng)前門店的商品總價(jià)<quota,那么最多只能扣減shopAmount的錢數(shù) 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) { // 不使用優(yōu)惠券 if (CollectionUtils.isEmpty(order.getCouponInfos())) { // dummy模板直接返回原價(jià),不進(jìn)行優(yōu)惠計(jì)算 return dummyTemplate; } // 獲取優(yōu)惠券的類別 // 目前每個(gè)訂單只支持單張優(yōu)惠券 CouponTemplateInfo template = order.getCouponInfos().get(0).getTemplate(); CouponType category = CouponType.convert(template.getType()); switch (category) { // 訂單滿減券 case MONEY_OFF: return moneyOffTemplate; // 隨機(jī)立減券 case RANDOM_DISCOUNT: return randomReductionTemplate; // 午夜下單優(yōu)惠翻倍 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; // 優(yōu)惠券結(jié)算 // 這里通過Factory類決定使用哪個(gè)底層Rule,底層規(guī)則對(duì)上層透明 @Override public ShoppingCart calculateOrderPrice(@RequestBody ShoppingCart cart) { log.info("calculate order price: {}", JSON.toJSONString(cart)); RuleTemplate ruleTemplate = couponProcessorFactory.getTemplate(cart); return ruleTemplate.calculate(cart); }
到此這篇關(guān)于SpringBoot 模板模式實(shí)現(xiàn)優(yōu)惠券邏輯的文章就介紹到這了,更多相關(guān)SpringBoot 優(yōu)惠券邏輯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析
這篇文章主要介紹了Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析,針對(duì)用戶所使用的語言來配置資源文件,需要的朋友可以參考下2016-04-04Mybatis批量插入大量數(shù)據(jù)的最優(yōu)方式總結(jié)
批量插入功能是我們?nèi)粘9ぷ髦斜容^常見的業(yè)務(wù)功能之一,下面這篇文章主要給大家總結(jié)介紹了關(guān)于Mybatis批量插入大量數(shù)據(jù)的幾種最優(yōu)方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03SpringBoot CountDownLatch多任務(wù)并行處理的實(shí)現(xiàn)方法
本篇文章主要介紹了SpringBoot CountDownLatch多任務(wù)并行處理的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04實(shí)例詳解Spring Boot實(shí)戰(zhàn)之Redis緩存登錄驗(yàn)證碼
本章簡(jiǎn)單介紹redis的配置及使用方法,本文示例代碼在前面代碼的基礎(chǔ)上進(jìn)行修改添加,實(shí)現(xiàn)了使用redis進(jìn)行緩存驗(yàn)證碼,以及校驗(yàn)驗(yàn)證碼的過程。感興趣的的朋友一起看看吧2017-08-08