策略模式
问题
Python 中如何实现策略模式?
答案
函数式策略(最 Pythonic)
Python 中函数是一等对象,策略可以直接用函数实现:
from typing import Callable
# 策略:不同的折扣计算方式
def no_discount(price: float) -> float:
return price
def percent_discount(price: float) -> float:
return price * 0.9 # 九折
def vip_discount(price: float) -> float:
return price * 0.8 # 八折
def fixed_discount(price: float) -> float:
return max(0, price - 20) # 减 20
# 上下文
class Order:
def __init__(self, items: list[float], discount: Callable[[float], float] = no_discount):
self.items = items
self.discount = discount
def total(self) -> float:
subtotal = sum(self.items)
return self.discount(subtotal)
# 使用
order = Order([100, 200, 50], discount=vip_discount)
print(order.total()) # 280.0
类策略(需要状态时)
from abc import ABC, abstractmethod
class PricingStrategy(ABC):
@abstractmethod
def calculate(self, price: float) -> float: ...
class PercentOff(PricingStrategy):
def __init__(self, percent: float):
self.percent = percent
def calculate(self, price: float) -> float:
return price * (1 - self.percent / 100)
class BuyNGetFree(PricingStrategy):
def __init__(self, buy: int, free: int):
self.buy = buy
self.free = free
def calculate(self, price: float) -> float:
# 简化:按比例折扣
return price * self.buy / (self.buy + self.free)
# 使用
strategy = PercentOff(20)
print(strategy.calculate(100)) # 80.0
策略注册表
strategies: dict[str, Callable[[float], float]] = {}
def register(name: str):
def decorator(func):
strategies[name] = func
return func
return decorator
@register("normal")
def normal(price: float) -> float:
return price
@register("vip")
def vip(price: float) -> float:
return price * 0.8
# 根据用户等级动态选择策略
def get_price(price: float, level: str) -> float:
strategy = strategies.get(level, normal)
return strategy(price)
常见面试问题
Q1: 策略模式和工厂模式的区别?
答案:
- 策略模式:选择不同的算法/行为
- 工厂模式:选择创建不同的对象
策略模式关注"怎么做",工厂模式关注"创建什么"。
Q2: 什么时候用函数策略、什么时候用类策略?
答案:
- 函数策略:无状态、逻辑简单——大多数场景
- 类策略:需要携带参数(如折扣比例)、需要多个方法、需要继承