测试模式将算法封装在独立的策略类中,使它们可以相互替换,从而让算法的变化独立于使用算法的客户端。
策略模式通常包含三个核心角色:
以下是一个电商系统中根据客户属性计算折扣的经典策略模式实现。
from abc import ABC, abstractmethod
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
# 策略接口:抽象基类
class Promotion(ABC):
@abstractmethod
def discount(self, order):
"""返回折扣金额(正值)"""
pass
# 具体策略1:积分折扣
class FidelityPromo(Promotion):
"""为积分为 1000 或以上的顾客提供 5% 折扣"""
def discount(self, order):
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
# 具体策略2:批量商品折扣
class BulkItemPromo(Promotion):
"""单个商品为 20 个或以上时提供 10% 折扣"""
def discount(self, order):
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() * .1
return discount
# 具体策略3:大订单折扣
class LargeOrderPromo(Promotion):
"""订单中的不同商品达到 10 个或以上时提供 7% 折扣"""
def discount(self, order):
if len(order.cart) >= 10:
return order.total() * .07
return 0
# 上下文类
class Order:
def __init__(self, customer, cart, promotion=None):
self.customer = customer
self.cart = list(cart)
self.promotion = promotion
def total(self):
return sum(item.total() for item in self.cart)
def due(self):
if self.promotion is None:
discount = 0
else:
discount = self.promotion.discount(self)
return self.total() - discount
def __repr__(self):
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
# 客户端代码
if __name__ == '__main__':
# 创建商品
apple = LineItem('apple', 20, 1.2)
iphone = LineItem('iphone', 1, 6000)
# 创建客户
vip_customer = Customer('VIP用户', 1500)
normal_customer = Customer('普通用户', 500)
# 应用不同策略
cart1 = [iphone]
cart2 = [apple]
# 高积分客户享受积分折扣
order1 = Order(vip_customer, cart1, promotion=FidelityPromo())
print(order1) # 输出: <Order total: 6000.00 due: 5700.00>
# 批量购买享受批量折扣
order2 = Order(normal_customer, cart2, promotion=BulkItemPromo())
print(order2) # 输出: <Order total: 24.00 due: 21.60>
↶ 返回首页 ↶