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,浅拷贝共享嵌套是深坑。
动手改
- 给
ServerSpec加一个disk_of(gb)方法,链出"16 核 / 64G 内存 / 200G 盘" - 从
base_vm克隆一台test_vm:CPU 保持 2,tags加"test",打印验证模板没被改动 - 把第 3 步里的
deepcopy故意换成.copy(),看看模板的tags会不会遭殃
下一章:结构型模式:适配器与外观 🐸