当前位置:首页>python>Python策略模式实战,告别if/elif嵌套

Python策略模式实战,告别if/elif嵌套

  • 2026-09-02 19:41:14
Python策略模式实战,告别if/elif嵌套
我们在开发过程中,经常会遇到同一个操作有多种实现方式的场景,比如计算折扣有常规折扣、季节性折扣、无折扣等。如果用if/elif来判断,代码会变得臃肿,而今天我们要说的策略模式,可以很好的解决这类问题。
废话就不多说了,我们就以电商订单结算为例,实现一个简单的策略模式,需求很简单,订单结算时,可根据不同场景应用不同的折扣策略。首先,我们定义3种折扣策略(每个策略封装一个算法):
class RegularDiscount:  def apply(self,price):    return price*0.95 # 常规折扣:95折class SeasonalDiscount:  def apply(self,price):    return price*0.8 #季节性折扣:8折class NoDiscount:  def apply(self,price):    return  price # 无折扣:原价结算
这三个策略类都有一个相同apply方法,这就是策略的统一接口,也是它们能相互替换 的关键。接下来,定义上下文(订单类),它负责使用策略,不好含任何折扣逻辑,只委托策略完成计算:
class Order:  def __init__(self,product,price,discount_strategy):    self.product = product # 商品名称    self.price = price # 商品原价    self.discount_strategy = discount_strategy #传入的折扣策略  def final_price(self):    # 委托策略计算最终价格,自己不写折扣逻辑    return self.discount_strategy.apply(self.price)  def summary(self):    #打印订单详情    print(f"商品:{self.product}")    print(f"原价:¥{self.price:.2f}")    print(f"折扣价:¥{self.final_price():.2f}")    print("-" * 30)
接下来我们创建几个订单,分别应用不同的折扣策略,看看效果:
# 无折扣订单,键盘order1 = Order("Keyboard",120.00,NoDiscount())# 常规折扣订单:笔记本支架order2 = Order("Laptop Stand",45.00,RegularDiscount())#季节性折扣订单:USB-C集线器order3 = Order("USB-C Hub",35.00,SeansonDiscount())# 打印订单详情order1.summary()order2.summary()order3.summary()
运行代码后,输出如下:
商品:Keyboard原价:¥120.00折扣价:¥120.00------------------------------商品:Laptop Stand原价:¥45.00折扣价:¥42.75------------------------------商品:USB-C Hub原价:¥35.00折扣价:¥28.00------------------------------
可以看出Order类完全不用判断用哪种折扣,只需要调用策略的apply方法即可。如果以后要增加新的折扣, 只需要增加一个策略类,不用修改Order类的任何代码,这就是开闭原则。
策略模式的优势之一是运行时切换策略,比如用户在购物过程中升级了会员,从无折扣切换到季节性折扣,不需要重启程序就能应用新策略。让我们以购物车为例子:
class ShoppingCart:    def __init__(self):        self.items = []  # 购物车商品列表        self.discount_strategy = NoDiscount()  # 默认无折扣    def add_item(self, name, price):        # 添加商品到购物车        self.items.append({"name": name, "price": price})    def set_discount(self, strategy):        # 动态切换折扣策略        self.discount_strategy = strategy        print(f"折扣策略已更新为:{strategy.__class__.__name__}")    def checkout(self):        # 结算:计算所有商品的折后总价        print("\n--- 结算详情 ---")        total = 0        for item in self.items:            discounted_price = self.discount_strategy.apply(item["price"])            print(f"{item['name']}: ${discounted_price:.2f}")            total += discounted_price        print(f"结算总价:${total:.2f}\n")
重点是set_discount方法,我们可以在任何时候替换策略,接下来我们测试一下:
# 初始化购物车cart = ShoppingCart()# 添加商品cart.add_item("Notebook", 15.00)cart.add_item("Desk Lamp", 40.00)cart.add_item("Monitor Riser", 25.00)# 第一次结算:普通用户(无折扣)cart.checkout()# 用户升级会员,切换为季节性折扣cart.set_discount(SeasonalDiscount())# 第二次结算:会员(8折)cart.checkout()

运行结果如下,清晰看到策略切换后的变化:

--- 结算详情 ---Notebook: $15.00Desk Lamp: $40.00Monitor Riser: $25.00结算总价:$80.00折扣策略已更新为:SeasonalDiscount--- 结算详情 ---Notebook: $12.00Desk Lamp: $32.00Monitor Riser: $20.00结算总价:$64.00
可以看到购物车本身逻辑没啥变化,只是切换了策略对象,就实现了不同的结算逻辑。
也许有时在使用时,创建了一个策略类,但是又忘记了写apply方法,程序在运行时才会报错,这在排查时就比较麻烦,我们可以通过Python的抽象类来解决,强制所有的策略类必须实现apply方法,只要没实现,在程序实例化时就报错。
from abc import ABC, abstractmethod# 定义抽象基类,规范策略接口class DiscountStrategy(ABC):    @abstractmethod  # 抽象方法,必须被子类实现    def apply(self, price: float) -> float:        pass
我们在实现折扣策略时,集成这个抽象类:
# 常规折扣:继承抽象基类,实现apply方法class RegularDiscount(DiscountStrategy):    def apply(self, price):        return price * 0.95# 季节性折扣:继承抽象基类,实现apply方法class SeasonalDiscount(DiscountStrategy):    def apply(self, price):        return price * 0.80# 无折扣:继承抽象基类,实现apply方法class NoDiscount(DiscountStrategy):    def apply(self, price):        return price
这时,如果再忘记实现apply程序就会报错了。
当然,策略模式虽然好用,却不是所有场景都适用。当代码中有冗长的if/elif判断,并且判断逻辑是不同的算法或者行为时;需要在运行时动态切换行为;需要构建可扩展的系统;需要独立测试不同的算法时都可以适用这个模式。
总之,策略模式的核心是用来解决问题,不是为了炫技而用。

最新文章

随机文章