【python 设计模式】策略模式

2024-01-10 00:00:00

测试模式将算法封装在独立的策略类中,使它们可以相互替换,从而让算法的变化独立于使用算法的客户端。

策略模式通常包含三个核心角色:

  1. 上下文(Context):持有一个策略对象的引用,负责维护对策略对象的引用,并提供一个接口让策略访问其数据。上下文类将算法的使用责任与算法的实现分离开来;
  2. 策略接口(Strategy):定义所有支持的算法的公共接口,通常是一个抽象类或接口。这个接口规范了每个策略类必须实现的方法;
  3. 具体策略(ConcreteStrategy):实现策略接口,提供具体的算法实现。每个具体策略类封装了一个特定的算法或行为;

电商折扣策略系统

以下是一个电商系统中根据客户属性计算折扣的经典策略模式实现。

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>

返回首页

本文总阅读量  次
皖ICP备17026209号-3
总访问量: 
总访客量: