在软件开发中,经常遇到多个算法或行为可以互换的情况,例如不同的支付方式、排序算法、日志记录方式等。如果使用 if-elseswitch-case 选择不同的策略,代码将变得复杂且难以维护。

策略模式(Strategy Pattern) 提供了一种定义一组算法,并在运行时选择合适的算法的方法,从而使代码更加灵活、可扩展、符合开闭原则(OCP)。本文将详细介绍策略模式的概念、应用场景,并通过 Python 代码示例展示其实现方式


一、策略模式的概念

策略模式(Strategy Pattern) 是一种行为型设计模式(Behavioral Pattern),其核心思想是:

定义一组可互换的算法(策略),将它们封装成独立的类,并在运行时动态选择其中一种。

UML 结构

    Context(上下文)
        │
    Strategy(抽象策略)
        │
    ┌───┴──────────┐
ConcreteStrategyA  ConcreteStrategyB(具体策略)

组成部分

  1. Strategy(策略接口):定义所有策略的公共方法。
  2. ConcreteStrategy(具体策略):实现 Strategy,提供具体算法。
  3. Context(上下文):持有 Strategy,并在运行时调用其方法。
  4. Client(客户端):选择合适的 Strategy 并传递给 Context

二、策略模式的应用场景

策略模式适用于以下场景:

支付方式(如支付宝、微信、信用卡支付)。

排序算法(如冒泡排序、快速排序、归并排序)。

日志记录(如本地日志、远程日志、数据库日志)。

数据压缩(如 ZIP、RAR、GZIP)。

促销策略(如满减、折扣、积分兑换)。


三、策略模式的 Python 实现

示例:选择不同的支付方式

假设开发一个在线支付系统,支持支付宝(Alipay)、微信支付(WeChatPay)、信用卡支付(CreditCardPay)

使用策略模式,可以封装不同的支付方式,并在运行时动态选择合适的支付策略,而不会影响 PaymentContext 代码。


代码实现

from abc import ABC, abstractmethod

# 1. 策略接口(Strategy)
class PaymentStrategy(ABC):
    """支付策略接口"""
    @abstractmethod
    def pay(self, amount):
        pass

# 2. 具体策略(ConcreteStrategy)
class Alipay(PaymentStrategy):
    """支付宝支付"""
    def pay(self, amount):
        return f"使用支付宝支付 {amount} 元 💰"

class WeChatPay(PaymentStrategy):
    """微信支付"""
    def pay(self, amount):
        return f"使用微信支付 {amount} 元 💵"

class CreditCardPay(PaymentStrategy):
    """信用卡支付"""
    def pay(self, amount):
        return f"使用信用卡支付 {amount} 元 💳"

# 3. 上下文(Context)
class PaymentContext:
    """支付上下文,持有支付策略"""
    def __init__(self, strategy: PaymentStrategy):
        self.strategy = strategy

    def set_strategy(self, strategy: PaymentStrategy):
        """更换支付策略"""
        self.strategy = strategy

    def pay(self, amount):
        """执行支付"""
        return self.strategy.pay(amount)

# 4. 客户端代码(Client)
if __name__ == "__main__":
    # 选择支付方式
    alipay = Alipay()
    wechat_pay = WeChatPay()
    credit_card_pay = CreditCardPay()

    # 创建支付上下文
    context = PaymentContext(alipay)
    print(context.pay(100))  # 使用支付宝支付 100 元 💰

    # 更换支付方式
    context.set_strategy(wechat_pay)
    print(context.pay(200))  # 使用微信支付 200 元 💵

    # 再次更换支付方式
    context.set_strategy(credit_card_pay)
    print(context.pay(300))  # 使用信用卡支付 300 元 💳

四、输出结果

使用支付宝支付 100 元 💰
使用微信支付 200 元 💵
使用信用卡支付 300 元 💳

代码解耦PaymentContext 只依赖 PaymentStrategy 接口,而不关心具体支付方式。

易于扩展:如果要增加 ApplePay,只需新增 ApplePay 类,无需修改 PaymentContext 代码。

可动态更换策略:可以在运行时切换不同支付方式,无需修改代码逻辑。


五、策略模式的优缺点

✅ 优点

符合开闭原则(OCP),新增策略不会影响已有代码。

解耦上下文和策略,可以随时更换算法,而不影响业务逻辑。

提高代码复用性,多个上下文可以复用相同策略。

❌ 缺点

可能增加类的数量,如果策略过多,可能会导致类的数量急剧增长。

不适用于简单场景,如果只有少量的可变逻辑,使用 if-else 可能更简单。


六、策略模式 vs 其他模式

设计模式 主要作用
策略模式(Strategy) 选择不同的算法或行为,支持动态替换
状态模式(State) 状态改变时自动切换行为
工厂模式(Factory) 创建不同对象,而不是动态替换行为
命令模式(Command) 将请求封装成对象,支持撤销/重做

如果要动态选择算法或行为,使用 策略模式

如果对象状态不同导致行为变化,使用 状态模式


七、策略模式的 Python 高级实现

Python 具有一等函数(First-Class Function)特性,可以使用函数代替策略类,使代码更加简洁。

使用 Python 函数实现策略模式

# 定义不同的支付策略
def alipay(amount):
    return f"使用支付宝支付 {amount} 元 💰"

def wechat_pay(amount):
    return f"使用微信支付 {amount} 元 💵"

def credit_card_pay(amount):
    return f"使用信用卡支付 {amount} 元 💳"

# 上下文类
class PaymentContext:
    def __init__(self, strategy):
        self.strategy = strategy

    def set_strategy(self, strategy):
        self.strategy = strategy

    def pay(self, amount):
        return self.strategy(amount)

# 测试代码
if __name__ == "__main__":
    context = PaymentContext(alipay)
    print(context.pay(100))

    context.set_strategy(wechat_pay)
    print(context.pay(200))

    context.set_strategy(credit_card_pay)
    print(context.pay(300))

减少类的数量,直接使用函数作为策略,代码更加简洁。

提高代码可读性,适用于策略逻辑较简单的情况。


八、总结

策略模式(Strategy Pattern) 是一种行为型设计模式,它将算法或行为封装成独立的策略类,并允许在运行时动态选择不同的策略,从而提高代码的灵活性和可扩展性

适用场景回顾

✔ 适用于多个算法可互换的情况(如支付、排序、日志记录)。

✔ 适用于希望在运行时动态选择策略的情况。

✔ 适用于希望避免 if-else 逻辑分支的情况。

在 Python 实现中,通过支付方式的示例展示了策略模式的使用,希望本文对你理解策略模式有所帮助!🚀


📌 有什么问题和经验想分享?欢迎在评论区交流、点赞、收藏、关注! 🎯

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐