Skip to content

策略、模板方法与 Pydantic

函数即策略、ABC 模板方法、Pydantic 建模与 DTO。

Updated View as Markdown
For humans

策略、模板方法与 Pydantic

三个考点串一条线:策略模式在 Python 里是传函数模板方法靠 ABC 定义骨架Pydantic 是数据建模的事实标准。分别答清楚,再对比。

策略模式:函数即策略

策略的本意:算法可替换,调用方不感知。Java 要接口加实现类,Python 直接传函数:

def price_regular(items):      # 策略 1
    return sum(items)

def price_vip(items):          # 策略 2
    return sum(items) * 0.8

def checkout(items, pricing):  # 策略注入
    return pricing(items)

checkout(items, price_vip)     # 换策略 = 换函数
  • 函数是一等公民,“策略对象”就是函数本身,不需要策略类
  • 需要带参策略时用闭包或 functools.partial 固化参数
  • 一组策略需要名字映射时用 dict 查表(strategy registry),比 if-elif 链干净
PRICING = {"regular": price_regular, "vip": price_vip}
checkout(items, PRICING[user.tier])

模板方法:ABC 定义骨架

模板方法的本意:算法骨架固定,步骤可变,子类实现步骤。Python 用抽象基类表达:

from abc import ABC, abstractmethod

class DataImporter(ABC):
    def import_data(self, source):          # 模板方法: 骨架固定
        data = self._fetch(source)          # 步骤 1
        cleaned = self._clean(data)         # 步骤 2
        self._save(cleaned)                 # 步骤 3

    @abstractmethod
    def _fetch(self, source): ...

    @abstractmethod
    def _clean(self, data): ...

    def _save(self, data):                  # 钩子: 有默认实现, 可覆盖
        db.insert(data)

class CsvImporter(DataImporter):            # 只实现步骤, 不碰骨架
    def _fetch(self, source): return read_csv(source)
    def _clean(self, data): return drop_na(data)

要点:import_data 骨架在父类,子类只填步骤;abstractmethod 强制子类实现。对比策略模式:模板方法固定骨架换步骤(继承),策略固定接口换算法(组合)

ABC 与 Protocol 再对比

维度 ABC(模板方法) Protocol(策略)
关系 继承(is-a) 结构匹配(acts-as)
强制实现 编译期/实例化报错 类型检查器提示
适用 骨架复用 能力约定

一句话:要复用骨架用 ABC,要约定能力用 Protocol。策略模式用 Protocol 标注更 Pythonic。

Pydantic:数据建模

Pydantic 是 FastAPI 的数据层,也是 Python 数据建模的事实标准:

from pydantic import BaseModel, Field

class Order(BaseModel):
    id: int
    user_id: int = Field(gt=0)
    items: list[str]
    total: float = Field(ge=0)

order = Order.model_validate(payload)   # 校验 + 转换
json_str = order.model_dump_json()      # 序列化

与设计模式的关系:

  • DTO(数据传输对象):FastAPI 的请求/响应模型就是 DTO,隔离内部模型与外部契约
  • Builder 的替代model_copy(update=...) 和 dataclasses 的 replace 处理“部分修改”场景,比 Builder 类轻得多
  • 校验即防御:边界在入口校验,业务层拿到的是合法数据(Fail Fast)

分层实践:请求模型(入参校验)→ 领域模型(业务逻辑)→ 响应模型(出参契约),用 model_validate 转换,三层职责分开。

面试追问

  1. Python 的策略模式怎么写? 传函数。带参策略用闭包或 partial,多策略用 dict 查表。不需要策略类
  2. 模板方法和策略的区别? 模板方法继承固定骨架换步骤;策略组合注入换算法。骨架复用用模板方法
  3. ABC 和 Protocol 怎么选? 复用骨架用 ABC,约定能力用 Protocol。策略标注用 Protocol
  4. Pydantic 在 FastAPI 里干什么? 请求/响应模型:校验入参、序列化出参。DTO 模式
  5. 模型分层怎么分? 请求模型、领域模型、响应模型三层,边界校验,内部隔离
Navigation

Type to search…

↑↓ navigate↵ selectEsc close