Python 建造者模式

建造者模式允许我们使用相同的构建过程创建不同的对象表示。想象一下建造房屋的过程:无论是建造别墅还是公寓,都需要经过打地基、建墙体、安装水电等步骤,但最终的结果却完全不同。

核心思想

建造者模式将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。这种模式特别适用于创建包含多个组成部分的复杂对象。


为什么需要建造者模式?

传统构造方法的问题

让我们先看一个不使用建造者模式的例子:

实例

class Computer:
    def __init__(self, cpu, memory, storage, graphics_card, monitor):
        self.cpu = cpu
        self.memory = memory
        self.storage = storage
        self.graphics_card = graphics_card
        self.monitor = monitor
   
    def __str__(self):
        return f"Computer: CPU={self.cpu}, Memory={self.memory}GB, Storage={self.storage}GB, Graphics={self.graphics_card}, Monitor={self.monitor}"

# 创建电脑对象
computer = Computer("Intel i7", 16, 512, "NVIDIA RTX 3060", "27寸 4K")
print(computer)

这种方法的缺点:

  • 构造函数参数过多,难以维护
  • 必须记住所有参数的顺序
  • 创建过程不够灵活
  • 代码可读性差

建造者模式的组成要素

建造者模式包含四个主要角色:

1. Product(产品)

要创建的复杂对象

2. Builder(抽象建造者)

定义创建产品各个部分的抽象接口

3. ConcreteBuilder(具体建造者)

实现 Builder 接口,构造和装配各个部件

4. Director(指挥者)

构建一个使用 Builder 接口的对象


完整代码实现

让我们通过一个电脑配置的例子来完整实现建造者模式:

1. 产品类(Product)

实例

class Computer:
    """电脑产品类"""
    def __init__(self):
        self.cpu = None
        self.memory = None
        self.storage = None
        self.graphics_card = None
        self.monitor = None
   
    def __str__(self):
        specs = []
        if self.cpu:
            specs.append(f"CPU: {self.cpu}")
        if self.memory:
            specs.append(f"内存: {self.memory}GB")
        if self.storage:
            specs.append(f"存储: {self.storage}GB")
        if self.graphics_card:
            specs.append(f"显卡: {self.graphics_card}")
        if self.monitor:
            specs.append(f"显示器: {self.monitor}")
       
        return "电脑配置:\n" + "\n".join(f"  - {spec}" for spec in specs)

2. 抽象建造者(Builder)

实例

from abc import ABC, abstractmethod

class ComputerBuilder(ABC):
    """电脑建造者抽象类"""
   
    def __init__(self):
        self.computer = Computer()
   
    @abstractmethod
    def build_cpu(self):
        pass
   
    @abstractmethod
    def build_memory(self):
        pass
   
    @abstractmethod
    def build_storage(self):
        pass
   
    @abstractmethod
    def build_graphics_card(self):
        pass
   
    @abstractmethod
    def build_monitor(self):
        pass
   
    def get_computer(self):
        return self.computer

3. 具体建造者(ConcreteBuilder)

实例

class GamingComputerBuilder(ComputerBuilder):
    """游戏电脑建造者"""
   
    def build_cpu(self):
        self.computer.cpu = "Intel i9-13900K"
   
    def build_memory(self):
        self.computer.memory = 32
   
    def build_storage(self):
        self.computer.storage = 2000  # 2TB
   
    def build_graphics_card(self):
        self.computer.graphics_card = "NVIDIA RTX 4090"
   
    def build_monitor(self):
        self.computer.monitor = "32寸 4K 144Hz"

class OfficeComputerBuilder(ComputerBuilder):
    """办公电脑建造者"""
   
    def build_cpu(self):
        self.computer.cpu = "Intel i5-13400"
   
    def build_memory(self):
        self.computer.memory = 16
   
    def build_storage(self):
        self.computer.storage = 512
   
    def build_graphics_card(self):
        self.computer.graphics_card = "集成显卡"
   
    def build_monitor(self):
        self.computer.monitor = "24寸 1080P"

4. 指挥者(Director)

实例

class ComputerDirector:
    """电脑建造指挥者"""
   
    def __init__(self, builder):
        self.builder = builder
   
    def construct_computer(self):
        """构建电脑的完整过程"""
        self.builder.build_cpu()
        self.builder.build_memory()
        self.builder.build_storage()
        self.builder.build_graphics_card()
        self.builder.build_monitor()
   
    def get_computer(self):
        return self.builder.get_computer()

使用示例

现在让我们看看如何使用建造者模式来创建不同类型的电脑:

实例

def main():
    print("=== 建造者模式演示 ===\n")
   
    # 创建游戏电脑
    print("1. 构建游戏电脑:")
    gaming_builder = GamingComputerBuilder()
    director = ComputerDirector(gaming_builder)
    director.construct_computer()
    gaming_computer = director.get_computer()
    print(gaming_computer)
   
    print("\n" + "="*50 + "\n")
   
    # 创建办公电脑
    print("2. 构建办公电脑:")
    office_builder = OfficeComputerBuilder()
    director = ComputerDirector(office_builder)
    director.construct_computer()
    office_computer = director.get_computer()
    print(office_computer)
   
    print("\n" + "="*50 + "\n")
   
    # 创建自定义电脑
    print("3. 自定义电脑构建:")
    custom_builder = CustomComputerBuilder()
    custom_builder.build_cpu("AMD Ryzen 7 7800X3D")
    custom_builder.build_memory(64)
    custom_builder.build_storage(4000)
    custom_builder.build_graphics_card("AMD RX 7900 XTX")
    custom_builder.build_monitor("34寸曲面带鱼屏")
    custom_computer = custom_builder.get_computer()
    print(custom_computer)

# 自定义建造者(可选步骤构建)
class CustomComputerBuilder:
    """自定义电脑建造者"""
   
    def __init__(self):
        self.computer = Computer()
   
    def build_cpu(self, cpu):
        self.computer.cpu = cpu
        return self  # 返回自身,支持链式调用
   
    def build_memory(self, memory):
        self.computer.memory = memory
        return self
   
    def build_storage(self, storage):
        self.computer.storage = storage
        return self
   
    def build_graphics_card(self, graphics_card):
        self.computer.graphics_card = graphics_card
        return self
   
    def build_monitor(self, monitor):
        self.computer.monitor = monitor
        return self
   
    def get_computer(self):
        return self.computer

if __name__ == "__main__":
    main()

建造者模式的变体

1. 流式接口建造者

实例

class Pizza:
    def __init__(self):
        self.size = None
        self.cheese = False
        self.pepperoni = False
        self.mushrooms = False
   
    def __str__(self):
        ingredients = []
        if self.cheese: ingredients.append("芝士")
        if self.pepperoni: ingredients.append("意大利香肠")
        if self.mushrooms: ingredients.append("蘑菇")
        return f"{self.size}寸披萨,配料: {', '.join(ingredients)}"

class PizzaBuilder:
    def __init__(self, size):
        self.pizza = Pizza()
        self.pizza.size = size
   
    def add_cheese(self):
        self.pizza.cheese = True
        return self
   
    def add_pepperoni(self):
        self.pizza.pepperoni = True
        return self
   
    def add_mushrooms(self):
        self.pizza.mushrooms = True
        return self
   
    def build(self):
        return self.pizza

# 使用流式接口
pizza = (PizzaBuilder(12)
         .add_cheese()
         .add_pepperoni()
         .add_mushrooms()
         .build())
print(pizza)

建造者模式的优缺点

优点

优点 说明
封装性好 构建过程与表示分离,客户端不需要知道内部细节
扩展性强 可以方便地增加新的具体建造者
更好的控制 可以更精细地控制构建过程
代码可读性 使用链式调用时代码更加清晰

缺点

缺点 说明
增加复杂性 需要定义多个类,增加了系统的复杂性
产品差异大时不适用 如果产品之间差异很大,建造者模式就不太适合
建造者依赖产品 建造者需要了解产品的具体细节

适用场景

适合使用建造者模式的情况:

  1. 创建复杂对象:需要创建包含多个组成部分的复杂对象
  2. 构建过程稳定:对象的构建过程相对稳定,但对象的组成部分经常变化
  3. 多种表示:需要创建的对象有多种不同的表示
  4. 避免重叠构造函数:避免使用包含多个参数的构造函数

实际应用示例:

  • 文档转换器:将文档转换为 PDF、Word、HTML 等不同格式
  • 餐品制作:制作不同套餐的餐品(汉堡、薯条、饮料的组合)
  • UI 组件构建:构建复杂的用户界面组件
  • 报表生成:生成包含不同部分(表头、数据、图表)的报表

实践练习

练习 1:实现汽车建造者

尝试实现一个汽车建造者模式,包含以下组件:

  • 引擎(汽油、电动、混合动力)
  • 车身颜色(红、蓝、黑、白)
  • 车轮尺寸(16寸、18寸、20寸)
  • 内饰(真皮、织物)

练习 2:改进电脑建造者

为电脑建造者添加以下功能:

  • 可选组件(如是否安装光驱)
  • 验证逻辑(如内存不能小于 4GB)
  • 价格计算功能

总结

建造者模式是一个强大的创建型设计模式,它通过将复杂对象的构建过程分解为多个简单的步骤,使得创建过程更加灵活和可控。虽然它增加了系统的复杂性,但在需要创建复杂对象且构建过程相对固定的场景下,建造者模式能够显著提高代码的可维护性和可扩展性。

记住设计模式的核心思想:不是为使用模式而使用模式,而是为了解决特定的设计问题。在实际开发中,要根据具体需求来决定是否使用建造者模式。