跳到主要内容

策略模式

问题

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: 什么时候用函数策略、什么时候用类策略?

答案

  • 函数策略:无状态、逻辑简单——大多数场景
  • 类策略:需要携带参数(如折扣比例)、需要多个方法、需要继承

相关链接