电商平台面试中的经典系统设计题。本文通过促销规则引擎设计,展示如何构建灵活可扩展的业务规则系统,csvosupport 助你掌握电商核心技术
📋 业务场景
设计一个促销规则引擎,支持:
- 满减(满1000
- 折扣折优惠)
- 买N送M(买2
- 组合优惠(A+B一起买打折
- 规则优先级和互斥
🎯 设计目标
- *灵活 - 易于添加新规则类
- *可组 - 支持规则组合
- 高性能 - 快速计算最优方
- *可维 - 清晰的代码结
💡 系统设计(csvosupport 方案
规则抽象
from abc import ABC, abstractmethod
from enum import Enum
class PromotionType(Enum):
DISCOUNT = "discount"
FULL_REDUCTION = "full_reduction"
BUY_N_GET_M = "buy_n_get_m"
COMBO = "combo"
class Promotion(ABC):
def __init__(self, promotion_id, name, priority=0):
self.id = promotion_id
self.name = name
self.priority = priority
self.exclusive_with = [] # 互斥规则
@abstractmethod
def can_apply(self, cart):
pass
@abstractmethod
def calculate_discount(self, cart):
pass
@abstractmethod
def apply(self, cart):
pass
class DiscountPromotion(Promotion):
def __init__(self, promotion_id, name, discount_rate,
applicable_products=None):
super().__init__(promotion_id, name)
self.discount_rate = discount_rate
self.applicable_products = applicable_products or []
def can_apply(self, cart):
if not self.applicable_products:
return True
return any(item.product_id in self.applicable_products
for item in cart.items)
def calculate_discount(self, cart):
total = 0
for item in cart.items:
if (not self.applicable_products or
item.product_id in self.applicable_products):
total += item.price * item.quantity
return total * (1 - self.discount_rate)
def apply(self, cart):
discount = self.calculate_discount(cart)
cart.add_discount(self.name, discount)
return cart
class FullReductionPromotion(Promotion):
def __init__(self, promotion_id, name, threshold, reduction):
super().__init__(promotion_id, name)
self.threshold = threshold
self.reduction = reduction
def can_apply(self, cart):
return cart.get_total() >= self.threshold
def calculate_discount(self, cart):
if self.can_apply(cart):
return self.reduction
return 0
def apply(self, cart):
if self.can_apply(cart):
cart.add_discount(self.name, self.reduction)
return cart
class BuyNGetMPromotion(Promotion):
def __init__(self, promotion_id, name, product_id, buy_n, get_m):
super().__init__(promotion_id, name)
self.product_id = product_id
self.buy_n = buy_n
self.get_m = get_m
def can_apply(self, cart):
quantity = cart.get_product_quantity(self.product_id)
return quantity >= self.buy_n
def calculate_discount(self, cart):
quantity = cart.get_product_quantity(self.product_id)
sets = quantity // self.buy_n
free_items = sets * self.get_m
item = cart.get_item(self.product_id)
return item.price * free_items if item else 0
def apply(self, cart):
discount = self.calculate_discount(cart)
if discount > 0:
cart.add_discount(self.name, discount)
return cart
购物车模
class CartItem:
def __init__(self, product_id, name, price, quantity):
self.product_id = product_id
self.name = name
self.price = price
self.quantity = quantity
def get_subtotal(self):
return self.price * self.quantity
class ShoppingCart:
def __init__(self):
self.items = []
self.discounts = []
self.applied_promotions = set()
def add_item(self, item):
# 检查是否已存在
for existing_item in self.items:
if existing_item.product_id == item.product_id:
existing_item.quantity += item.quantity
return
self.items.append(item)
def get_total(self):
return sum(item.get_subtotal() for item in self.items)
def get_product_quantity(self, product_id):
for item in self.items:
if item.product_id == product_id:
return item.quantity
return 0
def get_item(self, product_id):
for item in self.items:
if item.product_id == product_id:
return item
return None
def add_discount(self, name, amount):
self.discounts.append({'name': name, 'amount': amount})
def get_final_price(self):
total = self.get_total()
total_discount = sum(d['amount'] for d in self.discounts)
return max(0, total - total_discount)
促销引擎
class PromotionEngine:
def __init__(self):
self.promotions = []
def add_promotion(self, promotion):
self.promotions.append(promotion)
# 按优先级排序
self.promotions.sort(key=lambda p: p.priority, reverse=True)
def calculate_best_promotions(self, cart):
# 尝试所有可能的组合,找到最优方
best_cart = None
max_discount = 0
# 生成所有可能的促销组合
applicable_promotions = [p for p in self.promotions
if p.can_apply(cart)]
# 使用动态规划找最优组
for combination in self._generate_combinations(applicable_promotions):
test_cart = cart.copy()
# 检查互斥规
if self._has_conflict(combination):
continue
# 应用促销
for promo in combination:
promo.apply(test_cart)
discount = cart.get_total() - test_cart.get_final_price()
if discount > max_discount:
max_discount = discount
best_cart = test_cart
return best_cart or cart
def _generate_combinations(self, promotions):
# 生成所有可能的促销组合
from itertools import combinations
all_combinations = []
for r in range(len(promotions) + 1):
all_combinations.extend(combinations(promotions, r))
return all_combinations
def _has_conflict(self, promotions):
# 检查促销之间是否互斥
for i, p1 in enumerate(promotions):
for p2 in promotions[i+1:]:
if p2.id in p1.exclusive_with or p1.id in p2.exclusive_with:
return True
return False
💼 csvosupport 助力
设计模式 - 策略模式和工厂模 业务抽象 - 灵活的规则系 性能优化 - 最优方案计 *扩展 - 易于添加新规
联系 csvosupport,专业电商系统面试辅助!
*标签 #电商 #促销引擎 #系统设计 #设计模式 #VO辅助 #面试辅助 #一亩三分地
需要面试真题? 立刻联系微信 Coding0201,获得真题。