建造者模式:分步构建复杂对象
FreeGuideOnline
最新
2026-06-18
建造者模式:分步构建复杂对象
模式介绍
建造者模式(Builder Pattern)是一种创建型设计模式,用于分步骤创建复杂对象。它将对象的构造过程与表示分离,使相同的构建流程可以产生不同的产品形态。
当直接使用构造函数创建对象会变得臃肿、参数过多、可选参数逻辑混乱时,建造者模式提供了一种更加清晰、可读且易于维护的对象组装方案。该模式尤其适合参数组合爆炸或对象内部结构精密度高的场景。
核心参与者
| 角色 | 职责 |
|---|---|
| 产品(Product) | 最终构建出的复杂对象,包含多个部件。 |
| 抽象建造者(Builder) | 定义构建产品各部件的抽象接口或协议。 |
| 具体建造者(ConcreteBuilder) | 实现抽象建造者接口,组装具体部件并返回产品。 |
| 指挥者(Director) | 规定构建步骤的顺序和流程,调用建造者的方法完成对象创建。 |
结构图解
┌──────────┐
│ Director │
│ +construct│─────────────调用─────────────┐
└──────────┘ │
▼
┌─────────────────────┐ ┌───────────────────────┐
│ Builder │ │ ConcreteBuilder │
│ +buildPartA() │◄────── │ +buildPartA() │
│ +buildPartB() │ │ +buildPartB() │
│ +getResult() │ │ +getResult() -> Product│
└─────────────────────┘ └───────────┬───────────┘
│ 创建
▼
┌──────────────────┐
│ Product │
│ +partA, +partB │
└──────────────────┘
代码实战:组装一台自定义电脑
下面用 Python 实现一个可配置电脑的建造者,展示经典版建造者与流式接口的混合用法。产品是一台 Computer,包含 CPU、内存、硬盘、显卡等部件。
1. 产品类
class Computer:
def __init__(self):
self.cpu = None
self.ram = None
self.storage = None
self.gpu = None
def __str__(self):
return (f"Computer Specs:\n"
f"CPU: {self.cpu}\n"
f"RAM: {self.ram}\n"
f"Storage: {self.storage}\n"
f"GPU: {self.gpu}")
2. 抽象建造者与具体建造者
from abc import ABC, abstractmethod
class ComputerBuilder(ABC):
@abstractmethod
def set_cpu(self, cpu): pass
@abstractmethod
def set_ram(self, ram): pass
@abstractmethod
def set_storage(self, storage): pass
@abstractmethod
def set_gpu(self, gpu): pass
@abstractmethod
def get_result(self) -> Computer: pass
class GamingComputerBuilder(ComputerBuilder):
def __init__(self):
self.computer = Computer()
def set_cpu(self, cpu):
self.computer.cpu = cpu
return self # 支持链式调用
def set_ram(self, ram):
self.computer.ram = ram
return self
def set_storage(self, storage):
self.computer.storage = storage
return self
def set_gpu(self, gpu):
self.computer.gpu = gpu
return self
def get_result(self) -> Computer:
return self.computer
3. 指挥者(可选,但集中控制步骤)
class Director:
def __init__(self, builder: ComputerBuilder):
self.builder = builder
def build_gaming_pc(self):
self.builder.set_cpu("Intel i9-13900K")
self.builder.set_ram("32GB DDR5")
self.builder.set_storage("2TB NVMe SSD")
self.builder.set_gpu("NVIDIA RTX 4090")
def build_office_pc(self):
self.builder.set_cpu("Intel i5-13400")
self.builder.set_ram("16GB DDR4")
self.builder.set_storage("512GB SSD")
self.builder.set_gpu("Integrated Graphics")
4. 客户端调用
# 使用指挥者
builder = GamingComputerBuilder()
director = Director(builder)
director.build_gaming_pc()
pc = builder.get_result()
print(pc)
# 直接链式调用(无需 Director)
office_pc = (GamingComputerBuilder()
.set_cpu("AMD Ryzen 5 7600")
.set_ram("16GB DDR5")
.set_storage("1TB SSD")
.set_gpu("Integrated")
.get_result())
print(office_pc)
链式建造者:一种简化变体
在不需要 Director 的简单场景中,可以直接将构建步骤内聚到建造者内部,并通过返回 self 实现流式 API。这在配置类对象中非常流行。
class Burger:
def __init__(self):
self.bun = None
self.patty = None
self.cheese = False
self.veggies = []
class BurgerBuilder:
def __init__(self):
self.burger = Burger()
def with_bun(self, bun):
self.burger.bun = bun
return self
def with_patty(self, patty):
self.burger.patty = patty
return self
def add_cheese(self):
self.burger.cheese = True
return self
def add_veggies(self, *veggies):
self.burger.veggies.extend(veggies)
return self
def build(self):
return self.burger
# 使用
burger = (BurgerBuilder()
.with_bun("sesame")
.with_patty("beef")
.add_cheese()
.add_veggies("lettuce", "tomato")
.build())
进阶:多态建造者与不变式保护
在实际项目中,应当保护对象构建过程不被中断,避免创建出“半成品”对象。可以在 get_result() 或 build() 中增加完整性校验,必要时抛出异常或返回可选值。
def get_result(self) -> Computer:
if not self.computer.cpu or not self.computer.ram:
raise ValueError("CPU and RAM are mandatory components")
return self.computer
同时,可以为不同产品变体提供不同的建造者实现,利用多态让 Director 面向抽象接口编程,从而轻松切换家庭影院、游戏主机或办公笔记本的构建逻辑。
模式对比:建造者 vs 工厂 vs 抽象工厂
| 模式 | 关注点 | 使用时机 |
|---|---|---|
| 简单工厂/工厂方法 | 创建单个对象,隐藏实例化逻辑 | 对象创建简单,分支不多 |
| 抽象工厂 | 创建一系列相关对象族 | 需要保证产品族的一致性 |
| 建造者 | 逐步构造一个复杂对象 | 参数多、步骤复杂、要求不同表示 |
适用场景
- 构造函数拥有大量参数,且多数可选,或参数之间存在依赖关系。
- 需要创建不同表示的同一类对象(例如,不同配置的汽车、不同主题的文档)。
- 对象的构建过程必须遵循特定顺序或步骤。
- 希望将复杂对象的构建与使用分离,使代码更易维护。
优缺点一览
优点
- 分步骤控制对象创建,代码清晰度大幅提升。
- 隔离构建与表示,同样的流程可构建不同产品。
- 符合开闭原则:新增具体建造者无需修改现有代码。
- 支持链式调用,API 友好。
缺点
- 会产生多个类,增加代码量。
- 当产品间差异很小时可能显得冗余。
- 若产品组成部分固定且简单,使用建造者反而过度设计。
小结
建造者模式通过将对象的构造逻辑封装在独立类中,使得复杂的组装过程变得透明且可控。它不仅是处理“构造函数魔鬼参数”的利器,更是实现流畅 DSL 风格代码的基础。合理运用指挥者与建造者的组合,能让系统同时获得灵活性与稳定性。
试着为你项目中的报表生成器、查询条件构建器或游戏角色装配系统引入建造者模式,你会立刻感受到它带来的秩序感。