Python设计模式详解之20 ——策略模式

Strategy(策略)设计模式 是一种行为型设计模式,旨在定义一组算法或行为,并使它们可以相互替换,且独立于使用这些算法的客户端代码。它让代码更加灵活,便于扩展和维护。


1. 定义

Strategy 模式将算法的定义与使用分离,使得可以在运行时更改某些行为或算法而不影响客户端代码。这种模式鼓励用组合而非继承来实现动态行为。


2. 适用场景

  1. 需要在运行时动态切换算法或行为时。
    • 如支付方式选择(信用卡、PayPal 等)。
  2. 多个类只在算法或行为上有所不同时。
    • 避免将不同的算法硬编码在一个类中。
  3. 希望避免使用大量 if-elifswitch-case 语句时。

3. 结构

  1. Strategy(策略接口)
    定义所有支持的算法或行为的公共接口。

  2. ConcreteStrategy(具体策略)
    实现具体的算法或行为。

  3. Context(上下文)
    保存对 Strategy 对象的引用,供客户端调用和动态更换。


4. Python 实现

以下是实现 Strategy 模式的代码示例:

示例:支付系统的策略模式实现

from abc import ABC, abstractmethod

# Strategy 接口
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

# 具体策略:信用卡支付
class CreditCardPayment(PaymentStrategy):
    def __init__(self, card_number, card_holder):
        self.card_number = card_number
        self.card_holder = card_holder

    def pay(self, amount):
        print(f"Paid {amount} using Credit Card ({self.card_holder}).")

# 具体策略:PayPal 支付
class PayPalPayment(PaymentStrategy):
    def __init__(self, email):
        self.email = email

    def pay(self, amount):
        print(f"Paid {amount} using PayPal ({self.email}).")

# 具体策略:现金支付
class CashPayment(PaymentStrategy):
    def pay(self, amount):
        print(f"Paid {amount} using Cash.")

# Context
class PaymentContext:
    def __init__(self, strategy: PaymentStrategy):
        self.strategy = strategy

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

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

# 客户端
if __name__ == "__main__":
    # 使用 PayPal 支付
    paypal_payment = PayPalPayment(email="user@example.com")
    context = PaymentContext(strategy=paypal_payment)
    context.execute_payment(100)

    # 切换到信用卡支付
    credit_card_payment = CreditCardPayment(card_number="1234-5678-9876-5432", card_holder="John Doe")
    context.set_strategy(strategy=credit_card_payment)
    context.execute_payment(200)

    # 切换到现金支付
    cash_payment = CashPayment()
    context.set_strategy(strategy=cash_payment)
    context.execute_payment(50)

5. 优点和缺点

优点:

  1. 开闭原则:添加新策略时,不需要修改上下文和客户端代码。
  2. 消除条件语句:避免使用大量的 if-elifswitch-case 语句。
  3. 灵活性:可以在运行时更换算法。
  4. 可维护性:每种算法有独立的类,便于管理。

缺点:

  1. 增加类的数量:每种策略都需要一个独立的类。
  2. 可能导致复杂性:对于简单的问题,引入 Strategy 模式可能显得多余。
  3. 上下文依赖策略的实现:上下文需要知道策略的接口。

6. 扩展用法

6.1 数据处理场景

假设你有不同的排序算法,并希望根据数据特点选择最优算法。

class SortStrategy(ABC):
    @abstractmethod
    def sort(self, data):
        pass

class QuickSort(SortStrategy):
    def sort(self, data):
        print("Using QuickSort")
        return sorted(data)

class MergeSort(SortStrategy):
    def sort(self, data):
        print("Using MergeSort")
        return sorted(data)  # 实际可以实现自己的归并排序

class Context:
    def __init__(self, strategy: SortStrategy):
        self.strategy = strategy

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

    def execute_sort(self, data):
        return self.strategy.sort(data)

if __name__ == "__main__":
    data = [3, 1, 4, 1, 5]

    context = Context(strategy=QuickSort())
    print(context.execute_sort(data))

    context.set_strategy(MergeSort())
    print(context.execute_sort(data))

6.2 结合 Python 动态特性

Python 的动态特性可以减少显式类的数量,例如通过函数来实现策略模式。

# 策略定义为函数
def quick_sort(data):
    print("Using QuickSort")
    return sorted(data)

def merge_sort(data):
    print("Using MergeSort")
    return sorted(data)

class Context:
    def __init__(self, strategy):
        self.strategy = strategy

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

    def execute_sort(self, data):
        return self.strategy(data)

if __name__ == "__main__":
    data = [3, 1, 4, 1, 5]

    context = Context(strategy=quick_sort)
    print(context.execute_sort(data))

    context.set_strategy(merge_sort)
    print(context.execute_sort(data))

7. 设计原则

  • 遵循 开闭原则,可以轻松添加新策略而不修改现有代码。
  • 使用 组合优于继承 的原则,动态地组合行为。

8. 总结

Strategy 模式在需要动态改变算法、消除复杂条件分支或提高代码可扩展性时非常有用。Python 的动态特性(如函数作为对象)也为实现 Strategy 模式提供了简洁的方式,适合根据具体需求选择实现形式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾工

雁过留声

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值