策略模式替代 if-else 的实战方法
传统 if-else 写法(需要改进的代码)
def process_payment(payment_type, amount):
if payment_type == "alipay":
print(f"使用支付宝支付:{amount}元")
# 支付宝特定的处理逻辑
fee = amount * 0.001 # 手续费
return amount - fee
elif payment_type == "wechat":
print(f"使用微信支付:{amount}元")
# 微信特定的处理逻辑
fee = amount * 0.002
return amount - fee
elif payment_type == "bank_card":
print(f"使用银行卡支付:{amount}元")
# 银行卡特定的处理逻辑
fee = amount * 0.003
if amount > 1000:
fee = fee * 0.5 # 大额优惠
return amount - fee
else:
raise ValueError(f"不支持的支付方式:{payment_type}")
策略模式实现
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Dict, Optional
# 策略接口
class PaymentStrategy(ABC):
@abstractmethod
def process(self, amount: float) -> float:
"""处理支付,返回实际支付金额"""
pass
# 具体策略类
@dataclass
class AlipayStrategy(PaymentStrategy):
"""支付宝支付策略"""
def process(self, amount: float) -> float:
print(f"使用支付宝支付:{amount}元")
fee = amount * 0.001
return amount - fee
@dataclass
class WechatStrategy(PaymentStrategy):
"""微信支付策略"""
def process(self, amount: float) -> float:
print(f"使用微信支付:{amount}元")
fee = amount * 0.002
return amount - fee
@dataclass
class BankCardStrategy(PaymentStrategy):
"""银行卡支付策略"""
def process(self, amount: float) -> float:
print(f"使用银行卡支付:{amount}元")
fee = amount * 0.003
if amount > 1000:
fee = fee * 0.5 # 大额优惠
return amount - fee
# 上下文类
class PaymentContext:
def __init__(self):
self._strategies: Dict[str, PaymentStrategy] = {}
self._register_default_strategies()
def _register_default_strategies(self):
self._strategies["alipay"] = AlipayStrategy()
self._strategies["wechat"] = WechatStrategy()
self._strategies["bank_card"] = BankCardStrategy()
def register_strategy(self, name: str, strategy: PaymentStrategy):
"""动态注册新策略"""
self._strategies[name] = strategy
def execute_payment(self, payment_type: str, amount: float) -> float:
"""执行支付策略"""
strategy = self._strategies.get(payment_type)
if not strategy:
raise ValueError(f"不支持的支付方式:{payment_type}")
return strategy.process(amount)
# 使用示例
if __name__ == "__main__":
payment_context = PaymentContext()
# 使用既有策略
print(payment_context.execute_payment("alipay", 100))
print(payment_context.execute_payment("wechat", 200))
print(payment_context.execute_payment("bank_card", 1500))
# 动态添加新策略
class ApplePayStrategy(PaymentStrategy):
def process(self, amount: float) -> float:
print(f"使用Apple Pay支付:{amount}元")
return amount * 0.995 # 0.5%手续费
payment_context.register_strategy("apple_pay", ApplePayStrategy())
print(payment_context.execute_payment("apple_pay", 300))
更简单的策略模式实现(使用函数)
from typing import Dict, Callable
# 使用函数作为策略
def alipay_strategy(amount: float) -> float:
print(f"使用支付宝支付:{amount}元")
return amount * 0.999
def wechat_strategy(amount: float) -> float:
print(f"使用微信支付:{amount}元")
return amount * 0.998
def bank_card_strategy(amount: float) -> float:
print(f"使用银行卡支付:{amount}元")
fee = amount * 0.003
if amount > 1000:
fee *= 0.5
return amount - fee
class PaymentProcessor:
def __init__(self):
self.strategies: Dict[str, Callable] = {
"alipay": alipay_strategy,
"wechat": wechat_strategy,
"bank_card": bank_card_strategy
}
def process(self, payment_type: str, amount: float) -> float:
strategy = self.strategies.get(payment_type)
if not strategy:
raise ValueError(f"不支持的支付方式:{payment_type}")
return strategy(amount)
# 使用
processor = PaymentProcessor()
print(processor.process("alipay", 100))
print(processor.process("wechat", 200))
高级应用:动态策略加载
import json
from typing import Dict, Any
class DynamicStrategyManager:
def __init__(self, config_file: str = "strategies.json"):
self.strategies: Dict[str, PaymentStrategy] = {}
self.load_config(config_file)
def load_config(self, config_file: str):
"""从配置文件加载策略"""
with open(config_file, 'r') as f:
config = json.load(f)
for strategy_config in config.get("strategies", []):
name = strategy_config["name"]
class_path = strategy_config["class"]
params = strategy_config.get("params", {})
# 动态导入策略类
module_path, class_name = class_path.rsplit(".", 1)
module = __import__(module_path, fromlist=[class_name])
strategy_class = getattr(module, class_name)
# 实例化策略
strategy = strategy_class(**params)
self.strategies[name] = strategy
def process_payment(self, payment_type: str, amount: float) -> float:
strategy = self.strategies.get(payment_type)
if not strategy:
raise ValueError(f"未找到策略:{payment_type}")
return strategy.process(amount)
# strategies.json 示例
"""
{
"strategies": [
{
"name": "alipay",
"class": "strategies.AlipayStrategy",
"params": {}
},
{
"name": "custom_credit",
"class": "strategies.CreditCardStrategy",
"params": {"fee_rate": 0.005, "min_fee": 1}
}
]
}
"""
策略模式的优势
# ❌ 不好的做法(大量if-else)
def calculate_discount(user_type, amount):
if user_type == "normal":
return amount
elif user_type == "vip":
return amount * 0.9
elif user_type == "gold":
return amount * 0.8
elif user_type == "platinum":
return amount * 0.7
# ... 随着类型增加,代码越来越长
# ✅ 好的做法(策略模式)
from typing import Dict, Callable
class DiscountStrategy:
"""折扣策略管理"""
def __init__(self):
self._strategies: Dict[str, Callable] = {}
self._init_strategies()
def _init_strategies(self):
self.register("normal", lambda x: x)
self.register("vip", lambda x: x * 0.9)
self.register("gold", lambda x: x * 0.8)
self.register("platinum", lambda x: x * 0.7)
def register(self, user_type: str, strategy: Callable):
self._strategies[user_type] = strategy
def calculate(self, user_type: str, amount: float) -> float:
strategy = self._strategies.get(user_type)
if not strategy:
raise ValueError(f"未知用户类型:{user_type}")
return strategy(amount)
# 使用
discount = DiscountStrategy()
print(discount.calculate("vip", 100)) # 90.0
# 轻松扩展新策略
discount.register("super_vip", lambda x: x * 0.6)
print(discount.calculate("super_vip", 100)) # 60.0
关键收益
| 特点 | if-else方式 | 策略模式 |
|---|---|---|
| 可维护性 | 代码耦合,修改困难 | 低耦合,独立修改 |
| 可扩展性 | 需要修改原有代码 | 添加新类即可 |
| 可测试性 | 难以单独测试 | 可以单独测试每个策略 |
| 代码复用 | 不易复用 | 策略可被多个上下文复用 |
| 违反原则 | 违反开闭原则 | 遵循开闭原则 |
策略模式的核心思想是:将算法封装成独立的类,使它们可以互相替换,从而消除大量的条件判断。
