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ì)算類通過(guò)繼承 AbstractRuleTemplate,并實(shí)現(xiàn) calculateNewPrice 來(lái)編寫自己的優(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é)算
// 這里通過(guò)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實(shí)現(xiàn)RedisTemplate操作哈希數(shù)據(jù)
RedisTemplate是Spring Data Redis提供的一個(gè)用于操作Redis的模板類,本文主要介紹了java實(shí)現(xiàn)RedisTemplate操作哈希數(shù)據(jù),具有一定的參考價(jià)值,感興趣的可以了解一下2024-09-09
Java開(kāi)發(fā)Oracle數(shù)據(jù)庫(kù)連接JDBC Thin Driver 的三種方法
這篇文章主要介紹了Java開(kāi)發(fā)Oracle數(shù)據(jù)庫(kù)連接JDBC Thin Driver 的三種方法,需要的朋友可以參考下2015-12-12
springboot配置ssl后啟動(dòng)一直是端口被占用的解決
這篇文章主要介紹了springboot配置ssl后啟動(dòng)一直是端口被占用的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
mybatis 使用jdbc.properties文件設(shè)置不起作用的解決方法
這篇文章主要介紹了mybatis 使用jdbc.properties文件設(shè)置不起作用的解決方法,需要的朋友可以參考下2018-03-03
SpringBoot構(gòu)建RESTful API的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot構(gòu)建RESTful API的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
SpringBoot返回結(jié)果統(tǒng)一處理實(shí)例詳解
這篇文章主要為大家介紹了SpringBoot返回結(jié)果統(tǒng)一處理實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
關(guān)于apollo和Spring集成@Value注解通用解析
這篇文章主要介紹了關(guān)于apollo和Spring集成@Value注解通用解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
SSH框架網(wǎng)上商城項(xiàng)目第21戰(zhàn)之詳解易寶支付的流程
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第21戰(zhàn)之易寶支付的流程,感興趣的小伙伴們可以參考一下2016-06-06

