策略模式是定义一系列算法,把它们一一封装起来,并且使它们可以相互替换。本模式使得算法可以独立于使用它的客户而变化。
电商系统有个功能明显的可以使用"策略"模式,即根据用户的属性或订单中的商品数量计算折扣。
假如一个网店制定了一下的折扣规则:
- 有 1000 积分或以上的用户,每个订单享受 5% 的折扣;
- 同一个订单中,单个商品的数量达到20个及以上,享受 10% 的折扣;
- 订单中的不同商品达到10个及以上,享受 7% 的折扣;
简单起见,我们假设一个订单一次只能享受一个折扣;
# 使用函数实现策略模式,不使用抽象类;
from collections import namedtuple
# 客户类 名称 积分
Customer = namedtuple('Customer', ['name', 'fidelity'])
class LineItem:
def __init__(self, product, quantity, price):
# 产品名
self.product = product
# 数量
self.quantity = quantity
# 价格
self.price = price
def total(self):
"""总价格"""
return self.price * self.quantity
# 实现 Order 类,支持插入式折扣策略:
class Order: # 在"策略"模式中扮演上下文的角色
"""订单类"""
def __init__(self, customer, cart, promotion=None):
# 客户
self.customer = customer
# 购物车
self.cart = list(cart)
# 策略
self.promotion = promotion
def total(self):
"""购物车总金额"""
if not hasattr(self, '_total'):
self._total = sum(item.total() for item in self.cart)
return self._total
def due(self):
"""折扣后金额"""
if self.promotion is None:
discount = 0
else:
discount = self.promotion(self)
return self.total() - discount
def __repr__(self):
fmt = '<Order total: {:.2f} due: {:.2f}>'
return fmt.format(self.total(), self.due())
# 策略一:
def fidelity_promo(order: Order):
"""为 1000 及以上积分的客户提供 5% 的折扣"""
return order.total() * 0.5 if order.customer.fidelity >= 1000 else 0
# 策略二:
def bulk_item_promo(order: Order):
"""订单中单个商品为 20 个及以上时,为该商品提供 10% 的折扣"""
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() * 0.1
return discount
# 策略三:
def large_order_promo(order: Order):
"""订单中不同商品数量达到 10 个或以上时,提供 7% 的折扣"""
distinct_items = {item.product for item in order.cart}
if len(distinct_items) >= 10:
return order.total() * 0.07
return 0
# 策略列表
promos = [fidelity_promo, bulk_item_promo, large_order_promo]
def best_promo(order: Order):
"""选择可用的最佳策略"""
# 返回各策略中最大的折扣金额
return max(promo(order) for promo in promos)
if __name__ == '__main__':
John = Customer('John', 1000)
Jade = Customer('Jade', 1000)
carts = [
LineItem('香蕉', 4, 0.5),
LineItem('苹果', 20, 15),
LineItem('荔枝', 5, 5.0),
]
print(Order(John, carts, best_promo)) # <Order total: 327.00 due: 163.50>
本文介绍如何使用策略模式来实现电商系统的折扣计算功能,通过定义一系列算法并使其可互换,使得折扣策略能够独立于系统其他部分灵活调整。文章详细解释了三种不同的折扣策略,并展示了如何在订单中应用这些策略。

被折叠的 条评论
为什么被折叠?



