当if-else链出现分支逻辑需独立封装、频繁增删条件、复用相同参数或单分支超10行含状态时,应改用策略模式;如支付方式处理,可定义协议接口、具体策略类,通过字典注册与运行时选择实现解耦。

什么时候该用策略模式替代 if-else
当你的 if-else 链开始出现以下信号,就该考虑策略模式了:分支逻辑各自封装、后续要频繁增删条件、不同分支复用同一组输入参数、或者某个分支逻辑本身已超过 10 行且含独立状态。比如处理支付方式:if payment_type == "alipay": ... elif payment_type == "wechat": ... elif payment_type == "credit_card": ...——这类代码一旦加入风控校验、异步回调、失败重试,elif 块就会迅速失控。
定义策略接口与具体策略类
Python 没有 interface 关键字,但可以用抽象基类(ABC)或仅靠约定。推荐从协议(Protocol)或简单函数开始,避免过早抽象:
from typing import Protocol
class PaymentStrategy(Protocol):
def execute(self, amount: float, order_id: str) -> dict:
...
class AlipayStrategy:
def execute(self, amount: float, order_id: str) -> dict:
return {"status": "success", "channel": "alipay", "trace_id": f"ali_{order_id}"}
class WechatStrategy:
def execute(self, amount: float, order_id: str) -> dict:
return {"status": "success", "channel": "wechat", "trace_id": f"wx_{order_id}"}
注意:不要为每个策略加 __init__ 初始化一堆配置,除非真需要实例状态;多数场景下,策略对象是无状态的,可复用单例。
策略注册与运行时选择
硬编码 dict 映射最直接,也最容易调试:
立即学习“Python免费学习笔记(深入)”;
STRATEGIES = {
"alipay": AlipayStrategy(),
"wechat": WechatStrategy(),
"credit_card": CreditCardStrategy(),
}
def process_payment(payment_type: str, amount: float, order_id: str) -> dict:
strategy = STRATEGIES.get(payment_type)
if not strategy:
raise ValueError(f"Unsupported payment_type: {payment_type}")
return strategy.execute(amount, order_id)
常见坑:
-
STRATEGIES字典键名必须和外部传入的字符串严格一致(大小写、下划线),建议统一用str.lower()或预处理 - 别在
get()后用is None判断,直接用if not strategy更 Pythonic,但要注意策略类自身不能实现__bool__ - 如果策略需依赖注入(如数据库连接),不要在模块顶层实例化,改用工厂函数或延迟初始化
如何安全地扩展新策略
新增策略不是改 if-else,而是三步:写策略类 → 加入 STRATEGIES → 更新文档或枚举。关键点在于隔离变更范围:
- 所有策略类必须遵守同一签名(
execute方法参数与返回类型),可用typing.cast或 mypy 检查 - 避免策略之间互相 import,否则容易引发循环依赖;把共享工具函数抽到
utils/下 - 测试时不要 mock 整个策略字典,而应针对单个策略类单元测试,再对
process_payment做集成测试(只 mock 1–2 个策略)
最常被忽略的是错误传播:策略内部抛出的异常不应被吞掉,要让上层决定是重试、降级还是告警——策略只负责“怎么做”,不负责“做错了怎么办”。


















