Python 中的原型模式(Prototype Pattern)
原型模式是一种创建型设计模式,其核心思想是:
用一个已存在的对象(原型)作为模板,通过复制(克隆)来创建新的对象,而不是通过 new 或构造函数重新创建。
适用场景:
- 创建对象代价高昂(需要大量初始化、IO、网络请求等)
- 对象结构复杂,但大部分属性相似,只需微调
- 希望避免显式构造函数参数爆炸
- 需要快速生成大量相似对象(如游戏中的怪物、UI 组件、报表模板等)
原型模式的优点
- 隐藏创建细节,客户端只需调用
clone() - 性能好:复制比重新构建快得多
- 方便扩展:只需克隆再修改
Python 中的实现方式
Python 提供了非常方便的内置支持:copy 模块中的 copy()(浅拷贝)和 deepcopy()(深拷贝),以及 __copy__、__deepcopy__ 钩子。
1. 最简单的原型模式:使用 copy.deepcopy()
import copy
class Prototype:
def __init__(self, name, age, skills):
self.name = name
self.age = age
self.skills = skills # 列表,深拷贝时会复制
def clone(self):
return copy.deepcopy(self)
def __str__(self):
return f"{self.name} ({self.age}), skills: {self.skills}"
# 使用
if __name__ == "__main__":
original = Prototype("Alice", 28, ["Python", "Java", "SQL"])
clone1 = original.clone()
clone1.name = "Bob"
clone1.age = 30
clone1.skills.append("Go")
clone2 = original.clone()
clone2.name = "Charlie"
print("Original:", original)
print("Clone1: ", clone1)
print("Clone2: ", clone2)
输出:
Original: Alice (28), skills: ['Python', 'Java', 'SQL']
Clone1: Bob (30), skills: ['Python', 'Java', 'SQL', 'Go']
Clone2: Charlie (28), skills: ['Python', 'Java', 'SQL']
2. 更优雅的方式:自定义 __copy__ 和 __deepcopy__
import copy
class Employee:
def __init__(self, name, department, projects):
self.name = name
self.department = department
self.projects = projects # 列表
def __copy__(self):
# 浅拷贝:只复制对象本身,列表引用共享
new = self.__class__.__new__(self.__class__)
new.__dict__.update(self.__dict__)
return new
def __deepcopy__(self, memo=None):
# 深拷贝:递归复制所有可变对象
new = self.__class__.__new__(self.__class__)
new.__dict__.update({
'name': self.name,
'department': self.department,
'projects': copy.deepcopy(self.projects, memo)
})
return new
def clone(self, deep=False):
return copy.deepcopy(self) if deep else copy.copy(self)
def __str__(self):
return f"{self.name} in {self.department}, projects: {self.projects}"
# 测试
emp = Employee("Alice", "Engineering", ["Project A", "Project B"])
# 浅拷贝
emp_shallow = emp.clone(deep=False)
emp_shallow.name = "Bob"
emp_shallow.projects.append("Project C")
print("Original:", emp)
print("Shallow clone:", emp_shallow) # projects 列表是共享的
# 深拷贝
emp_deep = emp.clone(deep=True)
emp_deep.name = "Charlie"
emp_deep.projects.append("Project D")
print("Original (unchanged):", emp)
print("Deep clone:", emp_deep)
输出:
Original: Alice in Engineering, projects: ['Project A', 'Project B', 'Project C']
Shallow clone: Bob in Engineering, projects: ['Project A', 'Project B', 'Project C']
Original (unchanged): Alice in Engineering, projects: ['Project A', 'Project B', 'Project C']
Deep clone: Charlie in Engineering, projects: ['Project A', 'Project B', 'Project D']
3. 原型管理器(Prototype Registry)—— 注册原型并按名称克隆
import copy
class PrototypeRegistry:
def __init__(self):
self._prototypes = {}
def register(self, name, prototype):
self._prototypes[name] = prototype
def unregister(self, name):
del self._prototypes[name]
def clone(self, name, **attrs):
prototype = self._prototypes[name]
clone = copy.deepcopy(prototype)
clone.__dict__.update(attrs) # 覆盖或添加属性
return clone
# 使用
if __name__ == "__main__":
registry = PrototypeRegistry()
# 注册几种模板
registry.register("basic_car", Car("Basic Car", "Sedan", "Red", 100000))
registry.register("sports_car", Car("Sports Car", "Coupe", "Black", 300000))
# 克隆并修改
car1 = registry.clone("basic_car", color="Blue", price=120000)
car2 = registry.clone("sports_car", name="Ferrari", color="Yellow", price=500000)
print(car1)
print(car2)
原型模式 vs 其他创建型模式对比
| 模式 | 适用场景 | 是否需要构造函数 |
|---|---|---|
| 工厂方法 | 根据类型创建不同对象 | 是 |
| 抽象工厂 | 创建一组相关对象 | 是 |
| 建造者 | 复杂对象一步步构建 | 否(链式) |
| 原型 | 复制已有对象(尤其是初始化代价高) | 否(直接 clone) |
Python 中的实际推荐
- 大多数情况下,直接用
copy.deepcopy()就够了。 - 需要控制浅/深拷贝行为时,自定义
__copy__和__deepcopy__。 - 需要管理多种模板时,使用原型注册器(Registry)。
真实项目中的例子
- 游戏开发:克隆怪物、技能、物品
- 报表系统:克隆报表模板,再修改标题、字段
- 图形编辑器:复制图形对象
- 机器学习:复制模型配置,再微调
如果你想看更复杂的例子(如游戏角色原型、图形对象克隆、结合其他模式的实现),随时告诉我!