在前面的几种创建型模式中(工厂、抽象工厂、建造者),
我们解决的核心问题都是:
"对象该怎么创建?"
而原型模式关注的是另一件事:
"对象已经很复杂了,能不能直接复制一个?"
这就是 Prototype(原型)模式 要解决的问题。
一、原型模式要解决什么问题?
原型模式的核心思想一句话就够了:
通过复制已有对象来创建新对象,而不是通过
new或构造函数。
它适合解决这类场景:
- 对象创建成本很高(初始化复杂、耗时)
- 对象结构复杂,构造参数多
- 需要大量相似对象,只在少量属性上不同
- 希望避免大量重复的初始化逻辑
二、一个"很痛苦"的对象创建例子
先看一个不使用原型模式的写法。
python
class Report:
def __init__(self):
self.title = ""
self.header = ""
self.body = ""
self.footer = ""
self.styles = {}
self.permissions = []
def generate(self):
print(f"Generate report: {self.title}")
如果每次创建报告,都要这样:
python
r1 = Report()
r1.title = "Sales Report"
r1.header = "Company Header"
r1.body = "Sales Data"
r1.footer = "Company Footer"
r1.styles = {"font": "Arial"}
r1.permissions = ["admin", "manager"]
再来一个几乎一样的:
python
r2 = Report()
r2.title = "Inventory Report"
r2.header = "Company Header"
r2.body = "Inventory Data"
r2.footer = "Company Footer"
r2.styles = {"font": "Arial"}
r2.permissions = ["admin", "manager"]
问题非常明显:
- 大量重复初始化代码
- 很容易漏字段、写错字段
- 一旦结构调整,所有创建逻辑都要改
三、原型模式的核心思想
原型模式不是"从零创建",而是:
- 先准备一个原型对象
- 通过拷贝原型来创建新对象
- 再对差异部分进行修改
这在 Python 里天然就很顺手。
四、Python 中实现原型模式的关键工具
1️⃣ 浅拷贝与深拷贝
Python 标准库已经帮你准备好了:
python
import copy
copy.copy()→ 浅拷贝copy.deepcopy()→ 深拷贝
这是原型模式在 Python 中最常见的实现方式。
五、使用原型模式重构示例
1️⃣ 定义一个原型对象
python
import copy
class Report:
def __init__(self, title):
self.title = title
self.header = "Company Header"
self.body = ""
self.footer = "Company Footer"
self.styles = {"font": "Arial"}
self.permissions = ["admin", "manager"]
def clone(self):
return copy.deepcopy(self)
def generate(self):
print(f"Generate report: {self.title}")
2️⃣ 创建原型
python
base_report = Report("Base Report")
3️⃣ 基于原型复制新对象
python
sales_report = base_report.clone()
sales_report.title = "Sales Report"
sales_report.body = "Sales Data"
inventory_report = base_report.clone()
inventory_report.title = "Inventory Report"
inventory_report.body = "Inventory Data"
4️⃣ 使用
python
sales_report.generate()
inventory_report.generate()
六、为什么一定要用 deepcopy?
看这个例子:
python
r1 = base_report.clone()
r2 = base_report.clone()
r1.permissions.append("guest")
如果你用了 浅拷贝:
r1.permissionsr2.permissionsbase_report.permissions
很可能指向的是同一个列表对象。
这会导致非常隐蔽的 bug。
所以经验法则是:
原型模式中,除非你非常确定,否则优先使用
deepcopy。
七、原型注册表(Prototype Registry)
在复杂系统中,通常不止一个原型。
可以用一个"原型仓库"来统一管理。
python
class PrototypeRegistry:
def __init__(self):
self._prototypes = {}
def register(self, name, prototype):
self._prototypes[name] = prototype
def clone(self, name):
return self._prototypes[name].clone()
使用方式:
python
registry = PrototypeRegistry()
registry.register("base_report", base_report)
r = registry.clone("base_report")
r.title = "Custom Report"
八、原型模式的优缺点
✅ 优点
- 避免复杂、重复的构造逻辑
- 创建对象速度快
- 对象结构变化时,修改成本低
- 非常适合 Python 的动态特性
❌ 缺点
- 深拷贝可能有性能开销
- 对象之间的引用关系复杂时,调试成本高
- 不恰当使用浅拷贝容易引发隐藏 bug
九、原型模式适合用在什么地方?
非常适合以下场景:
- 模板对象、配置对象
- 报表、文档、表单生成
- 游戏中的角色、技能、道具
- UI 组件复制
- 需要"从现有状态复制"的对象
十、一句话总结
原型模式的本质不是"设计得多高大上",
而是让你:
少写构造代码,少踩初始化的坑。
在 Python 中:
copy.deepcopy- 再加一个
clone()方法
就已经是一个非常地道、实用的原型模式实现了。