建造者模式
建造者模式(Builder Pattern)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
问题定义
场景:创建复杂对象
# ❌ 问题:使用大量参数的构造函数
class Computer:
def __init__(
self,
cpu: str,
ram: int,
storage: int,
gpu: str = None,
monitor: str = None,
keyboard: str = None,
mouse: str = None
):
self.cpu = cpu
self.ram = ram
self.storage = storage
self.gpu = gpu
self.monitor = monitor
self.keyboard = keyboard
self.mouse = mouse
# 问题1:参数太多,难以记忆和调用
computer = Computer(
"Intel i7",
16,
512,
"NVIDIA RTX 3060",
"27寸显示器",
"机械键盘",
"无线鼠标"
)
# 问题2:参数顺序容易出错
# computer = Computer(16, "Intel i7", 512) # 错误!
# 问题3:可选参数导致多个构造函数重载
class Computer:
def __init__(self, cpu, ram, storage):
self.cpu = cpu
self.ram = ram
self.storage = storage
def with_gpu(self, gpu):
self.gpu = gpu
return self
def with_monitor(self, monitor):
self.monitor = monitor
return self
解决方案
建造者模式使用多个简单对象一步步构建复杂对象,提供清晰的构建接口。
classDiagram
class Builder {
<>
+reset()
+buildProduct() Product
}
class ConcreteBuilder {
-product: Product
+buildPartA()
+buildPartB()
+buildPartC()
+getProduct() Product
}
class Director {
-builder: Builder
+setBuilder()
+construct()
}
class Product {
+partA
+partB
+partC
}
Builder <|-- ConcreteBuilder
Director ..> Builder : uses
ConcreteBuilder ..> Product : creates
标准实现
产品类
class Computer:
"""电脑类 - 复杂产品"""
def __init__(self):
self.cpu = None
self.ram = None
self.storage = None
self.gpu = None
self.monitor = None
self.keyboard = None
self.mouse = None
self.os = None
self.software = []
def __str__(self):
"""展示配置"""
parts = [
f"CPU: {self.cpu}",
f"RAM: {self.ram}GB",
f"存储: {self.storage}GB",
f"GPU: {self.gpu or '无'}",
f"显示器: {self.monitor or '无'}",
f"键盘: {self.keyboard or '无'}",
f"鼠标: {self.mouse or '无'}",
f"操作系统: {self.os or '无'}",
f"软件: {', '.join(self.software) or '无'}"
]
return "电脑配置:\n" + "\n".join(parts)
建造者类
class ComputerBuilder:
"""电脑建造者"""
def __init__(self):
self.computer = Computer()
def set_cpu(self, cpu: str):
"""设置CPU"""
self.computer.cpu = cpu
return self
def set_ram(self, ram: int):
"""设置内存"""
self.computer.ram = ram
return self
def set_storage(self, storage: int):
"""设置存储"""
self.computer.storage = storage
return self
def set_gpu(self, gpu: str):
"""设置显卡"""
self.computer.gpu = gpu
return self
def set_monitor(self, monitor: str):
"""设置显示器"""
self.computer.monitor = monitor
return self
def set_keyboard(self, keyboard: str):
"""设置键盘"""
self.computer.keyboard = keyboard
return self
def set_mouse(self, mouse: str):
"""设置鼠标"""
self.computer.mouse = mouse
return self
def set_os(self, os: str):
"""设置操作系统"""
self.computer.os = os
return self
def add_software(self, software: str):
"""添加软件"""
self.computer.software.append(software)
return self
def build(self) -> Computer:
"""构建电脑"""
# 验证必要组件
if not self.computer.cpu or not self.computer.ram:
raise ValueError("CPU和RAM是必需的")
return self.computer
客户端使用
# 方式1:链式调用
gaming_pc = (ComputerBuilder()
.set_cpu("Intel i7")
.set_ram(32)
.set_storage(1000)
.set_gpu("NVIDIA RTX 3080")
.set_monitor("27寸 4K")
.set_keyboard("机械键盘")
.set_mouse("游戏鼠标")
.set_os("Windows 11")
.add_software("Steam")
.add_software("Discord")
.build())
print(gaming_pc)
print()
# 方式2:逐步构建
office_pc = ComputerBuilder()
office_pc.set_cpu("Intel i5")
office_pc.set_ram(16)
office_pc.set_storage(512)
office_pc.set_os("Windows 10")
print(office_pc.build())
print()
# 方式3:灵活配置
minimal_pc = (ComputerBuilder()
.set_cpu("Intel i3")
.set_ram(8)
.set_storage(256)
.build())
print(minimal_pc)
指导者模式
使用指导者封装构建流程:
class ComputerDirector:
"""电脑组装指导者 - 封装常用配置"""
def build_gaming_pc(self) -> Computer:
"""组装游戏电脑"""
return (ComputerBuilder()
.set_cpu("Intel i9")
.set_ram(64)
.set_storage(2000)
.set_gpu("NVIDIA RTX 4090")
.set_monitor("32寸 4K")
.set_keyboard("RGB机械键盘")
.set_mouse("电竞鼠标")
.set_os("Windows 11")
.build())
def build_office_pc(self) -> Computer:
"""组装办公电脑"""
return (ComputerBuilder()
.set_cpu("Intel i5")
.set_ram(16)
.set_storage(512)
.set_monitor("24寸显示器")
.set_keyboard("薄膜键盘")
.set_mouse("普通鼠标")
.set_os("Windows 10")
.build())
def build_server_pc(self) -> Computer:
"""组装服务器"""
return (ComputerBuilder()
.set_cpu("AMD EPYC")
.set_ram(256)
.set_storage(4000)
.set_os("Ubuntu Server")
.build())
# 使用
director = ComputerDirector()
gaming = director.build_gaming_pc()
print(gaming)
print()
office = director.build_office_pc()
print(office)
print()
server = director.build_server_pc()
print(server)
实战应用
应用1:SQL查询构建器
class SQLQuery:
"""SQL查询"""
def __init__(self):
self.select = []
self.from_table = None
self.where = []
self.group_by = []
self.order_by = []
self.limit = None
def __str__(self):
query = f"SELECT {', '.join(self.select) if self.select else '*'}"
if self.from_table:
query += f" FROM {self.from_table}"
if self.where:
query += f" WHERE {' AND '.join(self.where)}"
if self.group_by:
query += f" GROUP BY {', '.join(self.group_by)}"
if self.order_by:
query += f" ORDER BY {', '.join(self.order_by)}"
if self.limit:
query += f" LIMIT {self.limit}"
return query
class SQLBuilder:
"""SQL构建器"""
def __init__(self):
self.query = SQLQuery()
def select(self, *columns):
self.query.select.extend(columns)
return self
def from_table(self, table):
self.query.from_table = table
return self
def where(self, condition):
self.query.where.append(condition)
return self
def group_by(self, *columns):
self.query.group_by.extend(columns)
return self
def order_by(self, *columns):
self.query.order_by.extend(columns)
return self
def limit(self, count):
self.query.limit = count
return self
def build(self) -> SQLQuery:
if not self.query.from_table:
raise ValueError("FROM子句是必需的")
return self.query
# 使用
query1 = (SQLBuilder()
.select("name", "age", "email")
.from_table("users")
.where("age > 18")
.where("status = 'active'")
.order_by("name")
.limit(10)
.build())
print(query1)
# SELECT name, age, email FROM users WHERE age > 18 AND status = 'active' ORDER BY name LIMIT 10
query2 = (SQLBuilder()
.select("COUNT(*)", "category")
.from_table("products")
.group_by("category")
.order_by("COUNT(*) DESC")
.build())
print(query2)
# SELECT COUNT(*), category FROM products GROUP BY category ORDER BY COUNT(*) DESC
应用2:HTML构建器
class HTMLElement:
"""HTML元素"""
def __init__(self, tag_name):
self.tag_name = tag_name
self.attributes = {}
self.content = ""
self.children = []
def __str__(self):
attr_str = ""
if self.attributes:
attr_str = " " + " ".join(f'{k}="{v}"' for k, v in self.attributes.items())
if self.children:
children_str = "\n".join(str(child) for child in self.children)
return f"<{self.tag_name}{attr_str}>\n{children_str}\n</{self.tag_name}>"
else:
return f"<{self.tag_name}{attr_str}>{self.content}</{self.tag_name}>"
class HTMLBuilder:
"""HTML构建器"""
def __init__(self, tag_name):
self.element = HTMLElement(tag_name)
def add_attribute(self, name, value):
self.element.attributes[name] = value
return self
def set_content(self, content):
self.element.content = content
return self
def add_child(self, child_element):
self.element.children.append(child_element)
return self
def build(self) -> HTMLElement:
return self.element
# 使用
html = (HTMLBuilder("div")
.add_attribute("class", "container")
.add_child(
HTMLBuilder("h1")
.set_content("欢迎")
.build()
)
.add_child(
HTMLBuilder("p")
.set_content("这是一个示例")
.build()
)
.build())
print(html)
# <div class="container">
# <h1>欢迎</h1>
# <p>这是一个示例</p>
# </div>
应用3:URL构建器
from urllib.parse import urlencode
class URL:
"""URL对象"""
def __init__(self):
self.protocol = "https"
self.domain = ""
self.path = ""
self.params = {}
self.fragment = ""
def __str__(self):
url = f"{self.protocol}://{self.domain}"
if self.path:
url += f"/{self.path}"
if self.params:
url += f"?{urlencode(self.params)}"
if self.fragment:
url += f"#{self.fragment}"
return url
class URLBuilder:
"""URL构建器"""
def __init__(self):
self.url = URL()
def set_protocol(self, protocol):
self.url.protocol = protocol
return self
def set_domain(self, domain):
self.url.domain = domain
return self
def set_path(self, path):
self.url.path = path
return self
def add_param(self, key, value):
self.url.params[key] = value
return self
def set_fragment(self, fragment):
self.url.fragment = fragment
return self
def build(self) -> URL:
if not self.url.domain:
raise ValueError("域名是必需的")
return self.url
# 使用
url = (URLBuilder()
.set_protocol("https")
.set_domain("example.com")
.set_path("search")
.add_param("q", "python")
.add_param("page", "1")
.set_fragment("results")
.build())
print(url)
# https://example.com/search?q=python&page=1#results
不可变对象构建
使用建造者模式创建不可变对象:
class ImmutableComputer:
"""不可变电脑对象"""
def __init__(self, cpu, ram, storage, gpu=None):
self._cpu = cpu
self._ram = ram
self._storage = storage
self._gpu = gpu
@property
def cpu(self):
return self._cpu
@property
def ram(self):
return self._ram
@property
def storage(self):
return self._storage
@property
def gpu(self):
return self._gpu
class ImmutableComputerBuilder:
"""不可变电脑建造者"""
def __init__(self):
self._cpu = None
self._ram = None
self._storage = None
self._gpu = None
def cpu(self, cpu):
self._cpu = cpu
return self
def ram(self, ram):
self._ram = ram
return self
def storage(self, storage):
self._storage = storage
return self
def gpu(self, gpu):
self._gpu = gpu
return self
def build(self) -> ImmutableComputer:
if not self._cpu or not self._ram or not self._storage:
raise ValueError("CPU, RAM和Storage是必需的")
return ImmutableComputer(self._cpu, self._ram, self._storage, self._gpu)
# 使用
computer = (ImmutableComputerBuilder()
.cpu("Intel i7")
.ram(32)
.storage(1000)
.gpu("NVIDIA RTX 3080")
.build())
print(computer.cpu) # Intel i7
# computer.cpu = "AMD" # 报错!属性不可修改
优缺点
✅ 优点
| 优点 | 说明 |
|---|---|
| 分步构建 | 复杂对象分步骤创建 |
| 清晰接口 | 链式调用,易于理解 |
| 灵活配置 | 可选参数任意组合 |
| 不可变对象 | 可创建不可变对象 |
| 代码复用 | 指导者封装常用配置 |
❌ 缺点
| 缺点 | 说明 |
|---|---|
| 类数量增加 | 产品类 + 建造者类 |
| 复杂度增加 | 简单对象可能过度设计 |
| 构建时间长 | 需要多步调用 |
与其他模式的关系
| 模式 | 关系 |
|---|---|
| 抽象工厂 | 抽象工厂创建产品族,建造者构建复杂产品 |
| 原型 | 结合使用,先原型后构建 |
| 组合 | 建造者常用于构建组合结构 |
本章要点
- ✅ 建造者模式分步构建复杂对象
- ✅ 链式调用提供清晰接口
- ✅ 指导者封装常用配置
- ✅ 可创建不可变对象
- ✅ 适用于参数多、步骤多的复杂对象
下一步:抽象工厂模式 🚀