🐸 青蛙编程网
首页 / Python / 设计模式 / 3. 创建型模式:建造者与原型

3. 创建型模式:建造者与原型

这是什么:建造者 = 用链式调用一步步组装复杂对象,每一步都在说人话;原型 = 从一个现成模板克隆出新对象,再改掉不同之处。还是创建型:管对象怎么"生"得舒服。

为什么用:配置项一多,构造函数就变成 Server(8, 32, 40, True, False)——谁能记住第 3 个参数是什么?而"100 台虚拟机和 1 台模板差不多"的需求,一个个从零建太费劲,克隆再改两个字段才是人干的事。

如何用:先给服务器配置写一个链式建造者,再从一份虚拟机模板克隆出开发机。

建造者:链式调用自带说明书

每个方法设置一项配置后 return self,就能一路 . 下去,每个参数自带名字:

class ServerSpec:
    def __init__(self):
        self.cpu = 1            # 默认 1 核
        self.memory = 2         # 默认 2G
        self.disk = 40          # 默认 40G

    def cpu_of(self, cores):
        self.cpu = cores
        return self             # 返回自己,才能继续 . 下去

    def memory_of(self, gb):
        self.memory = gb
        return self

    def build(self):
        return f"{self.cpu} 核 / {self.memory}G 内存 / {self.disk}G 盘"

server = ServerSpec().cpu_of(8).memory_of(32).build()
print(server)

你会看到:

8 核 / 32G 内存 / 40G 盘

对比 ServerSpec(8, 32):cpu_of(8).memory_of(32) 不用查文档就知道每个数是什么。没设置的项目自动用默认值——磁盘没提,就用默认的 40G。

原型:从模板克隆,改差异

一批虚拟机的配置大同小异,维护一份模板,克隆出实例再改不同处:

import copy

base_vm = {"cpu": 2, "memory": 4, "disk": 40, "region": "cn-north", "tags": ["web"]}

dev_vm = copy.deepcopy(base_vm)   # 从模板克隆一份完整的
dev_vm["cpu"] = 4
dev_vm["tags"].append("dev")

print(dev_vm)
print(base_vm)

你会看到:

{'cpu': 4, 'memory': 4, 'disk': 40, 'region': 'cn-north', 'tags': ['web', 'dev']}
{'cpu': 2, 'memory': 4, 'disk': 40, 'region': 'cn-north', 'tags': ['web']}

dev_vm 改了 CPU、加了标签,模板 base_vm 原封不动——这就是"克隆"该有的效果。

关键坑:浅拷贝不是克隆

把上面的 deepcopy 换成 dict 自带的 copy()(浅拷贝),外层是新字典,嵌套的列表还是共享同一份:

shallow = base_vm.copy()          # 浅拷贝:只复制外层
shallow["tags"].append("oops")
print(base_vm["tags"])            # 模板竟然也被改了

你会看到:

['web', 'oops']

所以做原型克隆,含嵌套结构一律 copy.deepcopy——"深"到最里层,全是独立副本。

本章解读

代码 作用
return self 建造者的灵魂:返回自己,链式调用才能继续
.build() 建造者收口:组装完毕,产出最终对象
copy.deepcopy(x) 深拷贝:连同嵌套结构一起复制,彻底独立
x.copy() 浅拷贝:只复制最外层,嵌套部分仍然共享
原型 "模板 + 克隆 + 改差异",适合批量相似对象

记忆口诀

链式 .cpu_of(8) 步步说人话,return self 是它的引擎;要克隆就用 deepcopy,浅拷贝共享嵌套是深坑。

动手改

  1. 给 ServerSpec 加一个 disk_of(gb) 方法,链出"16 核 / 64G 内存 / 200G 盘"
  2. 从 base_vm 克隆一台 test_vm:CPU 保持 2,tags 加 "test",打印验证模板没被改动
  3. 把第 3 步里的 deepcopy 故意换成 .copy(),看看模板的 tags 会不会遭殃

下一章:结构型模式:适配器与外观 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。