Python 建造者模式

Python 中的建造者模式(Builder Pattern)

建造者模式是一种创建型设计模式,用于将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

核心目的
当一个对象有许多可选参数、配置项,或者构建步骤复杂时,使用建造者模式可以让代码更清晰、可读性更高,避免出现“ telescoping constructor”(超长构造函数)问题。

典型应用场景

  • 创建复杂对象(如 HTML、SQL 查询、配置文件、Pizza、电脑配置等)
  • 需要一步步配置对象的属性
  • 同一个构建过程需要产生不同配置的对象
  • 构建过程必须保持稳定,但最终产品有多种变体

建造者模式 vs 工厂模式

  • 工厂模式关注“创建什么对象”
  • 建造者模式关注“如何一步步构建一个复杂对象”

Python 实现示例:定制 Pizza

我们用一个经典例子——定制披萨,来演示建造者模式。

from abc import ABC, abstractmethod
from typing import List

# 最终产品:Pizza
class Pizza:
    def __init__(self):
        self.size: str = ""
        self.crust: str = ""
        self.sauce: str = ""
        self.cheese: str = ""
        self.toppings: List[str] = []

    def __str__(self):
        return f"""
Pizza:
  Size: {self.size}
  Crust: {self.crust}
  Sauce: {self.sauce}
  Cheese: {self.cheese}
  Toppings: {', '.join(self.toppings) or 'None'}
""".strip()


# 抽象建造者
class PizzaBuilder(ABC):
    @abstractmethod
    def set_size(self, size: str):
        pass

    @abstractmethod
    def set_crust(self, crust: str):
        pass

    @abstractmethod
    def set_sauce(self, sauce: str):
        pass

    @abstractmethod
    def add_cheese(self, cheese: str):
        pass

    @abstractmethod
    def add_topping(self, topping: str):
        pass

    @abstractmethod
    def get_pizza(self) -> Pizza:
        pass


# 具体建造者:Margherita Pizza Builder
class MargheritaPizzaBuilder(PizzaBuilder):
    def __init__(self):
        self.pizza = Pizza()

    def set_size(self, size: str):
        self.pizza.size = size
        return self  # 支持链式调用

    def set_crust(self, crust: str):
        self.pizza.crust = crust
        return self

    def set_sauce(self, sauce: str):
        self.pizza.sauce = "Tomato"  # Margherita 固定番茄酱
        return self

    def add_cheese(self, cheese: str):
        self.pizza.cheese = "Mozzarella"
        return self

    def add_topping(self, topping: str):
        if topping.lower() == "basil":
            self.pizza.toppings.append(topping)
        return self

    def get_pizza(self) -> Pizza:
        return self.pizza


# 具体建造者:Pepperoni Pizza Builder
class PepperoniPizzaBuilder(PizzaBuilder):
    def __init__(self):
        self.pizza = Pizza()

    def set_size(self, size: str):
        self.pizza.size = size
        return self

    def set_crust(self, crust: str):
        self.pizza.crust = crust
        return self

    def set_sauce(self, sauce: str):
        self.pizza.sauce = sauce
        return self

    def add_cheese(self, cheese: str):
        self.pizza.cheese = cheese
        return self

    def add_topping(self, topping: str):
        self.pizza.toppings.append(topping)
        return self

    def get_pizza(self) -> Pizza:
        return self.pizza


# 指挥者(Director):可选,用于定义构建顺序
class PizzaChef:
    def __init__(self, builder: PizzaBuilder):
        self.builder = builder

    def make_pizza(self, size: str):
        return (self.builder
                .set_size(size)
                .set_crust("Thin")
                .set_sauce("Tomato")
                .add_cheese("Mozzarella")
                .get_pizza())


# 使用示例
if __name__ == "__main__":
    # 方式1:使用指挥者(标准流程)
    margherita_builder = MargheritaPizzaBuilder()
    chef = PizzaChef(margherita_builder)
    pizza1 = chef.make_pizza("Large")
    pizza1.toppings.append("Basil")  # 额外添加
    print(pizza1)

    # 方式2:手动链式构建(更灵活,Python 中常见)
    pepperoni_builder = PepperoniPizzaBuilder()
    pizza2 = (pepperoni_builder
              .set_size("Medium")
              .set_crust("Stuffed")
              .set_sauce("Spicy Tomato")
              .add_cheese("Cheddar")
              .add_topping("Pepperoni")
              .add_topping("Mushrooms")
              .add_topping("Olives")
              .get_pizza())
    print(pizza2)

Python 中的简化版(更 Pythonic)

Python 支持链式调用(返回 self)和默认参数,因此可以实现更简洁的建造者:

class Pizza:
    def __init__(self, size="Medium"):
        self.size = size
        self.crust = "Classic"
        self.sauce = "Tomato"
        self.cheese = "Mozzarella"
        self.toppings = []

    def set_crust(self, crust):
        self.crust = crust
        return self

    def set_sauce(self, sauce):
        self.sauce = sauce
        return self

    def add_topping(self, topping):
        self.toppings.append(topping)
        return self

    def __str__(self):
        return f"{self.size} {self.crust} pizza with {self.sauce}, {self.cheese}, toppings: {self.toppings}"


# 直接使用(无需额外 Builder 类)
pizza = (Pizza("Large")
         .set_crust("Thin")
         .set_sauce("BBQ")
         .add_topping("Chicken")
         .add_topping("Onions"))
print(pizza)

这种方式在 Python 社区更常见,因为简洁且易读。

建造者模式结构总结

角色职责
Product复杂对象(Pizza)
Builder抽象接口,定义构建步骤
ConcreteBuilder实现具体构建逻辑,返回产品
Director(可选)编排构建顺序

优点

  • 构建过程与表示分离
  • 一步步构建,代码可读性高
  • 支持链式调用(Fluent Interface)
  • 易于扩展新产品类型

缺点

  • 如果产品简单,引入建造者会过度设计
  • 需要更多类

实际推荐(Python 项目中)

  • 对象参数不多:直接用默认参数 + 可选参数
  • 参数中等(5-10个):用链式方法(Fluent Builder)
  • 参数很多或构建复杂:使用完整建造者模式 + Director

如果你想看其他例子(如构建 SQL 查询、HTML 字符串、DataFrame 配置、游戏角色创建等),欢迎告诉我!

文章已创建 3511

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部