第5章 原型模式
学习目标
完成本章学习后,读者将能够:
- 理解原型模式的核心概念、形式化定义与理论基础
- 掌握Python中实现原型模式的多种方式及其适用场景
- 深入理解深拷贝与浅拷贝的语义差异与实现机制
- 识别并处理循环引用、不可变对象等复杂克隆场景
- 设计高性能的原型注册表与原型工厂
- 评估原型模式与其他创建型模式的权衡取舍
5.1 模式定义
5.1.1 形式化定义
原型模式(Prototype Pattern) 使用原型实例指定要创建对象的类型,通过复制这个原型来创建新对象。
从形式化角度,原型模式可定义为:
$$ \text{Prototype}: \mathcal{O} \xrightarrow{\text{clone}} \mathcal{O}' $$
其中:
- $\mathcal{O}$ 为原型对象(Prototype Object)
- $\mathcal{O}'$ 为克隆对象(Cloned Object)
- $\text{clone}$ 为克隆操作,满足 $\text{type}(\mathcal{O}') = \text{type}(\mathcal{O})$
克隆语义的形式化约束:
$$ \forall p \in \text{Prototype}, \forall c = p.\text{clone}(): \begin{cases} \text{type}(c) = \text{type}(p) & \text{(类型一致性)} \ c \neq p & \text{(对象独立性)} \ \text{equivalent}(c, p) & \text{(状态等价性)} \end{cases} $$
深拷贝与浅拷贝的形式化区分:
$$ \text{ShallowCopy}(o) = o' \land \forall r \in \text{refs}(o): r' = r $$
$$ \text{DeepCopy}(o) = o' \land \forall r \in \text{refs}(o): r' = \text{DeepCopy}(r) $$
其中 $\text{refs}(o)$ 表示对象 $o$ 的所有引用类型属性集合。
5.1.2 历史背景与学术渊源
原型模式的概念可追溯至多个学术领域:
1. 生物学隐喻(1980s)
术语"Prototype"源自希腊语"πρωτότυπος"(prōtotypos),意为"原始模型"。在生物学中,原型指物种的典型形态。软件工程借用此概念,表示作为复制模板的对象实例。
2. Self语言的影响(1987)
David Ungar和Randall Smith在Self语言中首创基于原型的对象模型,与传统的基于类的模型形成对比:
类继承模型:Class → Instance
原型模型:Prototype → CloneSelf语言证明,无需类的概念也能实现面向对象编程,原型本身即是对象,新对象通过克隆现有对象创建。
3. GoF分类(1994)
Gamma等人在《Design Patterns》中将原型模式归类为创建型模式,强调其"通过复制创建对象"的核心思想,并定义了Prototype接口与ConcretePrototype的标准结构。
4. 现代演进
现代编程语言对原型模式的支持呈现两种路径:
- 内置支持型:Python的
copy模块、Java的Cloneable接口、C#的ICloneable - 语言级原型:JavaScript的原型链继承机制
5.1.3 模式动机
原型模式解决以下核心问题:
问题1:对象创建成本高昂
class ComplexSimulation:
def __init__(self):
self.data = self._expensive_computation()
def _expensive_computation(self) -> dict:
import time
time.sleep(5)
return {"result": "computed"}每次创建新实例需执行耗时计算,而克隆可跳过初始化过程。
问题2:对象结构复杂
class ComplexObject:
def __init__(self):
self.nested = NestedObject()
self.nested.deep = DeepObject()
self.nested.deep.values = [1, 2, 3]手动复制复杂嵌套结构容易出错,原型模式提供标准化复制机制。
问题3:运行时动态类型
def process(obj: Prototype):
new_obj = obj.clone()无需知道具体类型即可创建副本,实现与具体类解耦。
5.1.4 UML结构模型
┌─────────────────────────────────────────────────────────────┐
│ Prototype Pattern │
│ 结构模型 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────┐
│ <<interface>> │
│ Prototype │
├─────────────────────────┤
│ + clone(): Prototype │◄─────────── 克隆接口
│ + deep_clone(): Prototype│
└────────────△────────────┘
│
│ implements
│
┌────────────┴────────────┐ ┌─────────────────────────┐
│ ConcretePrototype │ │ PrototypeRegistry │
├─────────────────────────┤ ├─────────────────────────┤
│ - field1: Type │ │ - prototypes: Dict │
│ - field2: Type │ ├─────────────────────────┤
│ - _nested: Object │ │ + register(name, proto) │
├─────────────────────────┤ │ + unregister(name) │
│ + clone(): Prototype │ │ + get_clone(name) │
│ + deep_clone(): Prototype│ │ + list_prototypes() │
└─────────────────────────┘ └─────────────────────────┘
│ │
│ 注册/获取 │
└────────────────────────┘参与者职责:
| 参与者 | 职责 |
|---|---|
| Prototype | 声明克隆接口,定义克隆操作的契约 |
| ConcretePrototype | 实现克隆方法,处理具体类型的复制逻辑 |
| PrototypeRegistry | 管理原型实例,提供按名称获取克隆的服务 |
| Client | 调用原型克隆方法创建新对象 |
5.2 Python实现机制
5.2.1 Python拷贝机制深度解析
Python的copy模块提供了两种拷贝机制,理解其内部实现对于正确使用原型模式至关重要。
拷贝机制原理图:
┌─────────────────────────────────────────────────────────────┐
│ Python 对象拷贝机制 │
└─────────────────────────────────────────────────────────────┘
原始对象 浅拷贝 深拷贝
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Object │ │ Object │ │ Object │
├─────────────┤ ├─────────────┤ ├─────────────┤
│ id: 1001 │ │ id: 2001 │ │ id: 2001 │
│ x: 10 │◄── 新值 ──────│ x: 10 │ │ x: 10 │
│ list ───────┼──┐ │ list ───────┼──┐ │ list ───────┼──┐
└─────────────┘ │ └─────────────┘ │ └─────────────┘ │
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ List │ │ List │ │ List │
├──────────┤ ├──────────┤ ├──────────┤
│ id: 3001 │◄── 共享引用 ─────│ id: 3001 │ │ id: 3002 │
│ [1,2,3] │ │ [1,2,3] │ │ [1,2,3] │
└──────────┘ └──────────┘ └──────────┘
▲
│
独立副本 ───┘浅拷贝实现原理:
import copy
from typing import Any
def shallow_copy_analysis():
"""
浅拷贝创建新对象,但内部引用仍指向原对象
"""
original = {
'name': 'Alice',
'scores': [85, 90, 78],
'metadata': {'age': 25}
}
shallow = copy.copy(original)
print(f"原始对象ID: {id(original)}")
print(f"浅拷贝ID: {id(shallow)}")
print(f"原始scores ID: {id(original['scores'])}")
print(f"浅拷贝scores ID: {id(shallow['scores'])}")
shallow['scores'].append(95)
print(f"修改后原始scores: {original['scores']}")
shallow_copy_analysis()深拷贝实现原理:
import copy
def deep_copy_analysis():
"""
深拷贝递归复制所有嵌套对象
"""
original = {
'name': 'Alice',
'scores': [85, 90, 78],
'metadata': {'age': 25}
}
deep = copy.deepcopy(original)
print(f"原始scores ID: {id(original['scores'])}")
print(f"深拷贝scores ID: {id(deep['scores'])}")
deep['scores'].append(95)
print(f"修改后原始scores: {original['scores']}")
print(f"修改后深拷贝scores: {deep['scores']}")
deep_copy_analysis()拷贝性能对比:
import copy
import time
from dataclasses import dataclass
from typing import List
@dataclass
class ComplexObject:
id: int
name: str
values: List[int]
metadata: dict
def benchmark_copy():
obj = ComplexObject(
id=1,
name="test",
values=list(range(10000)),
metadata={f"key_{i}": f"value_{i}" for i in range(1000)}
)
iterations = 1000
start = time.perf_counter()
for _ in range(iterations):
copy.copy(obj)
shallow_time = time.perf_counter() - start
start = time.perf_counter()
for _ in range(iterations):
copy.deepcopy(obj)
deep_time = time.perf_counter() - start
print(f"浅拷贝 {iterations} 次: {shallow_time:.4f}秒")
print(f"深拷贝 {iterations} 次: {deep_time:.4f}秒")
print(f"深拷贝耗时倍数: {deep_time/shallow_time:.2f}x")
benchmark_copy()5.2.2 基于ABC的标准实现
from abc import ABC, abstractmethod
from typing import TypeVar, Generic
import copy
T = TypeVar('T', bound='Prototype')
class Prototype(ABC):
"""
原型抽象基类,定义克隆接口契约
设计原则:
- 接口隔离:仅定义克隆相关方法
- 单一职责:专注于对象复制功能
"""
@abstractmethod
def clone(self) -> T:
"""
创建当前对象的浅拷贝
Returns:
当前对象的浅拷贝副本
"""
pass
@abstractmethod
def deep_clone(self) -> T:
"""
创建当前对象的深拷贝
Returns:
当前对象的深拷贝副本
"""
pass
def __copy__(self) -> T:
"""支持copy.copy()协议"""
return self.clone()
def __deepcopy__(self, memo: dict) -> T:
"""支持copy.deepcopy()协议"""
return self.deep_clone()
class Shape(Prototype):
"""
图形基类,展示标准原型实现
"""
def __init__(
self,
x: float = 0,
y: float = 0,
color: str = "black",
opacity: float = 1.0
):
self.x = x
self.y = y
self.color = color
self.opacity = opacity
self._id = id(self)
def clone(self) -> 'Shape':
new_shape = copy.copy(self)
new_shape._id = id(new_shape)
return new_shape
def deep_clone(self) -> 'Shape':
return copy.deepcopy(self)
def move(self, dx: float, dy: float) -> None:
self.x += dx
self.y += dy
def __eq__(self, other: object) -> bool:
if not isinstance(other, Shape):
return False
return (
self.x == other.x and
self.y == other.y and
self.color == other.color and
self.opacity == other.opacity
)
def __hash__(self) -> int:
return hash((self.x, self.y, self.color, self.opacity))
def __repr__(self) -> str:
return f"Shape(x={self.x}, y={self.y}, color='{self.color}', opacity={self.opacity})"
class Rectangle(Shape):
"""矩形具体原型"""
def __init__(
self,
x: float = 0,
y: float = 0,
width: float = 0,
height: float = 0,
color: str = "black",
opacity: float = 1.0
):
super().__init__(x, y, color, opacity)
self.width = width
self.height = height
@property
def area(self) -> float:
return self.width * self.height
@property
def perimeter(self) -> float:
return 2 * (self.width + self.height)
def clone(self) -> 'Rectangle':
new_rect = copy.copy(self)
new_rect._id = id(new_rect)
return new_rect
def __repr__(self) -> str:
return f"Rectangle(x={self.x}, y={self.y}, w={self.width}, h={self.height}, color='{self.color}')"
class Circle(Shape):
"""圆形具体原型"""
def __init__(
self,
x: float = 0,
y: float = 0,
radius: float = 0,
color: str = "black",
opacity: float = 1.0
):
super().__init__(x, y, color, opacity)
self.radius = radius
@property
def area(self) -> float:
import math
return math.pi * self.radius ** 2
@property
def circumference(self) -> float:
import math
return 2 * math.pi * self.radius
def clone(self) -> 'Circle':
new_circle = copy.copy(self)
new_circle._id = id(new_circle)
return new_circle
def __repr__(self) -> str:
return f"Circle(x={self.x}, y={self.y}, r={self.radius}, color='{self.color}')"
def demo_abc_prototype():
original = Rectangle(10, 20, 100, 50, "red")
shallow = original.clone()
deep = original.deep_clone()
print(f"原始: {original}")
print(f"浅拷贝: {shallow}")
print(f"深拷贝: {deep}")
print(f"原始与浅拷贝相等: {original == shallow}")
print(f"原始与深拷贝相等: {original == deep}")
print(f"原始ID: {original._id}, 浅拷贝ID: {shallow._id}")
demo_abc_prototype()5.2.3 基于Protocol的现代实现
from typing import Protocol, TypeVar, runtime_checkable
import copy
T = TypeVar('T')
@runtime_checkable
class Cloneable(Protocol):
"""
克隆协议,使用Python 3.8+ Protocol实现结构化类型
优势:
- 支持鸭子类型,无需显式继承
- 运行时可检查协议一致性
- 与静态类型检查器良好集成
"""
def clone(self) -> 'Cloneable':
...
def deep_clone(self) -> 'Cloneable':
...
class Document:
"""
文档类,隐式实现Cloneable协议
无需显式继承,只需实现协议方法
"""
def __init__(
self,
title: str = "",
content: str = "",
author: str = "",
tags: list = None,
metadata: dict = None
):
self.title = title
self.content = content
self.author = author
self.tags = tags or []
self.metadata = metadata or {}
self._version = 1
def clone(self) -> 'Document':
"""浅拷贝:共享tags和metadata引用"""
new_doc = Document(
title=self.title,
content=self.content,
author=self.author,
tags=self.tags,
metadata=self.metadata
)
new_doc._version = self._version
return new_doc
def deep_clone(self) -> 'Document':
"""深拷贝:完全独立的副本"""
new_doc = copy.deepcopy(self)
new_doc._version = self._version
return new_doc
def __repr__(self) -> str:
return f"Document(title='{self.title}', author='{self.author}', tags={self.tags})"
class Spreadsheet:
"""电子表格类,同样隐式实现Cloneable协议"""
def __init__(self, name: str = "", rows: int = 100, cols: int = 26):
self.name = name
self.rows = rows
self.cols = cols
self._data = [[None for _ in range(cols)] for _ in range(rows)]
self._formulas = {}
def clone(self) -> 'Spreadsheet':
new_sheet = Spreadsheet(self.name, self.rows, self.cols)
new_sheet._data = self._data
new_sheet._formulas = self._formulas
return new_sheet
def deep_clone(self) -> 'Spreadsheet':
return copy.deepcopy(self)
def set_cell(self, row: int, col: int, value) -> None:
if 0 <= row < self.rows and 0 <= col < self.cols:
self._data[row][col] = value
def get_cell(self, row: int, col: int):
if 0 <= row < self.rows and 0 <= col < self.cols:
return self._data[row][col]
return None
def __repr__(self) -> str:
return f"Spreadsheet(name='{self.name}', {self.rows}x{self.cols})"
def clone_anything(obj: Cloneable) -> Cloneable:
"""
泛型克隆函数,接受任何实现Cloneable协议的对象
"""
return obj.deep_clone()
def demo_protocol_prototype():
doc = Document(
title="设计模式手册",
content="第一章:创建型模式",
author="设计团队",
tags=["设计模式", "软件工程"],
metadata={"department": "研发部"}
)
sheet = Spreadsheet("销售数据", 50, 10)
sheet.set_cell(0, 0, "产品")
sheet.set_cell(0, 1, "销量")
print(f"文档是否实现Cloneable: {isinstance(doc, Cloneable)}")
print(f"表格是否实现Cloneable: {isinstance(sheet, Cloneable)}")
doc_clone = clone_anything(doc)
sheet_clone = clone_anything(sheet)
print(f"原始文档: {doc}")
print(f"克隆文档: {doc_clone}")
print(f"原始表格: {sheet}")
print(f"克隆表格: {sheet_clone}")
demo_protocol_prototype()5.2.4 自定义__copy__与__deepcopy__
import copy
from typing import Any, Dict, List, Optional, Set
from weakref import WeakValueDictionary
class GraphNode:
"""
图节点类,展示自定义拷贝协议
处理场景:
- 循环引用
- 共享资源
- 弱引用
"""
_instances: WeakValueDictionary = WeakValueDictionary()
def __init__(self, name: str, value: Any = None):
self.name = name
self.value = value
self.neighbors: List['GraphNode'] = []
self._resources: Set[str] = set()
self._parent: Optional['GraphNode'] = None
def add_neighbor(self, node: 'GraphNode') -> None:
self.neighbors.append(node)
node._parent = self
def add_resource(self, resource: str) -> None:
self._resources.add(resource)
def __copy__(self) -> 'GraphNode':
"""
自定义浅拷贝实现
策略:
- 复制基本属性
- 共享邻居引用
- 共享资源集合
- 重置父引用
"""
new_node = GraphNode(self.name, self.value)
new_node.neighbors = self.neighbors
new_node._resources = self._resources
return new_node
def __deepcopy__(self, memo: Dict[int, Any]) -> 'GraphNode':
"""
自定义深拷贝实现,正确处理循环引用
memo字典记录已拷贝对象,防止无限递归
策略:
- 使用memo检测循环引用
- 递归拷贝邻居
- 拷贝资源集合
- 重建父引用关系
"""
obj_id = id(self)
if obj_id in memo:
return memo[obj_id]
new_node = GraphNode(self.name, copy.deepcopy(self.value, memo))
memo[obj_id] = new_node
new_node.neighbors = [
copy.deepcopy(neighbor, memo)
for neighbor in self.neighbors
]
new_node._resources = copy.deepcopy(self._resources, memo)
for neighbor in new_node.neighbors:
neighbor._parent = new_node
return new_node
def __repr__(self) -> str:
neighbor_names = [n.name for n in self.neighbors]
return f"GraphNode('{self.name}', neighbors={neighbor_names})"
def demo_custom_copy():
node_a = GraphNode("A", value={"data": 1})
node_b = GraphNode("B", value={"data": 2})
node_c = GraphNode("C", value={"data": 3})
node_a.add_neighbor(node_b)
node_a.add_neighbor(node_c)
node_b.add_neighbor(node_a)
node_a.add_resource("resource_1")
print("原始图结构:")
print(f" {node_a}")
print(f" {node_b}")
print(f" {node_c}")
shallow_a = copy.copy(node_a)
print("\n浅拷贝后:")
print(f" 原始A邻居ID: {[id(n) for n in node_a.neighbors]}")
print(f" 浅拷贝A邻居ID: {[id(n) for n in shallow_a.neighbors]}")
print(f" 邻居共享: {id(node_a.neighbors[0]) == id(shallow_a.neighbors[0])}")
deep_a = copy.deepcopy(node_a)
print("\n深拷贝后:")
print(f" 原始A邻居ID: {[id(n) for n in node_a.neighbors]}")
print(f" 深拷贝A邻居ID: {[id(n) for n in deep_a.neighbors]}")
print(f" 邻居独立: {id(node_a.neighbors[0]) != id(deep_a.neighbors[0])}")
demo_custom_copy()5.2.5 原型注册表模式
from abc import ABC, abstractmethod
from typing import Dict, TypeVar, Generic, Callable, Optional, Any
from dataclasses import dataclass, field
from enum import Enum
import copy
import json
T = TypeVar('T')
class PrototypeRegistry(Generic[T]):
"""
泛型原型注册表
功能:
- 原型注册与注销
- 按名称获取克隆
- 支持克隆后回调
- 原型元数据管理
"""
def __init__(self):
self._prototypes: Dict[str, T] = {}
self._metadata: Dict[str, Dict[str, Any]] = {}
self._post_clone_callbacks: Dict[str, Callable[[T], None]] = {}
def register(
self,
name: str,
prototype: T,
metadata: Optional[Dict[str, Any]] = None,
post_clone_callback: Optional[Callable[[T], None]] = None
) -> None:
"""
注册原型
Args:
name: 原型名称
prototype: 原型实例
metadata: 原型元数据(描述、分类等)
post_clone_callback: 克隆后回调函数
"""
self._prototypes[name] = prototype
self._metadata[name] = metadata or {}
if post_clone_callback:
self._post_clone_callbacks[name] = post_clone_callback
def unregister(self, name: str) -> bool:
"""注销原型,返回是否成功"""
if name in self._prototypes:
del self._prototypes[name]
del self._metadata[name]
self._post_clone_callbacks.pop(name, None)
return True
return False
def get_clone(self, name: str, deep: bool = True) -> T:
"""
获取原型克隆
Args:
name: 原型名称
deep: 是否深拷贝
Returns:
克隆后的对象
"""
if name not in self._prototypes:
raise KeyError(f"原型 '{name}' 未注册")
prototype = self._prototypes[name]
if deep:
clone = copy.deepcopy(prototype)
else:
clone = copy.copy(prototype)
if name in self._post_clone_callbacks:
self._post_clone_callbacks[name](clone)
return clone
def get_metadata(self, name: str) -> Dict[str, Any]:
"""获取原型元数据"""
return self._metadata.get(name, {})
def list_prototypes(self) -> list[str]:
"""列出所有注册的原型名称"""
return list(self._prototypes.keys())
def list_by_category(self, category: str) -> list[str]:
"""按分类列出原型"""
return [
name for name, meta in self._metadata.items()
if meta.get('category') == category
]
class DocumentCategory(Enum):
REPORT = "report"
CONTRACT = "contract"
LETTER = "letter"
FORM = "form"
@dataclass
class DocumentTemplate:
"""文档模板原型"""
name: str
category: DocumentCategory
title_template: str
content_template: str
required_fields: list = field(default_factory=list)
optional_fields: list = field(default_factory=list)
styles: dict = field(default_factory=dict)
def clone(self, **overrides) -> 'DocumentTemplate':
new_template = copy.deepcopy(self)
for key, value in overrides.items():
if hasattr(new_template, key):
setattr(new_template, key, value)
return new_template
def render(self, **values) -> dict:
"""渲染模板"""
missing = set(self.required_fields) - set(values.keys())
if missing:
raise ValueError(f"缺少必填字段: {missing}")
rendered = {
'title': self.title_template.format(**values),
'content': self.content_template.format(**values),
'styles': self.styles
}
return rendered
def setup_document_registry() -> PrototypeRegistry[DocumentTemplate]:
"""设置文档模板注册表"""
registry = PrototypeRegistry[DocumentTemplate]()
def increment_version(doc: DocumentTemplate) -> None:
if hasattr(doc, '_version'):
doc._version += 1
report_template = DocumentTemplate(
name="月度报告",
category=DocumentCategory.REPORT,
title_template="{company} {month}月度报告",
content_template="""
报告日期: {date}
报告人: {author}
## 工作总结
{summary}
## 下月计划
{plan}
""".strip(),
required_fields=['company', 'month', 'date', 'author', 'summary', 'plan'],
optional_fields=['attachments'],
styles={'font': 'Arial', 'size': 12}
)
registry.register(
"monthly_report",
report_template,
metadata={'category': 'report', 'description': '月度工作报告模板'},
post_clone_callback=increment_version
)
contract_template = DocumentTemplate(
name="服务合同",
category=DocumentCategory.CONTRACT,
title_template="{service_type}服务合同",
content_template="""
甲方: {party_a}
乙方: {party_b}
服务内容: {service_content}
服务期限: {duration}
服务费用: {fee}
签署日期: {sign_date}
""".strip(),
required_fields=['service_type', 'party_a', 'party_b', 'service_content', 'duration', 'fee', 'sign_date'],
styles={'font': 'SimSun', 'size': 14}
)
registry.register(
"service_contract",
contract_template,
metadata={'category': 'contract', 'description': '标准服务合同模板'}
)
return registry
def demo_prototype_registry():
registry = setup_document_registry()
print("已注册模板:")
for name in registry.list_prototypes():
meta = registry.get_metadata(name)
print(f" - {name}: {meta.get('description', 'N/A')}")
report = registry.get_clone("monthly_report")
report.name = "2024年1月报告"
print(f"\n克隆的模板: {report.name}")
print(f"分类: {report.category.value}")
print(f"必填字段: {report.required_fields}")
rendered = report.render(
company="科技有限公司",
month="2024年1月",
date="2024-01-31",
author="张三",
summary="完成了产品开发的主要工作",
plan="下月进行测试和部署"
)
print(f"\n渲染结果:\n{rendered['title']}")
demo_prototype_registry()5.3 高级克隆技术
5.3.1 循环引用处理
import copy
from typing import Optional, List, Set
from dataclasses import dataclass, field
@dataclass
class Employee:
"""
员工类,展示循环引用处理
循环引用场景:
- 员工 → 部门 → 员工
- 经理 → 下属 → 经理
"""
name: str
employee_id: str
department: Optional['Department'] = None
manager: Optional['Employee'] = None
subordinates: List['Employee'] = field(default_factory=list)
def __deepcopy__(self, memo: dict) -> 'Employee':
obj_id = id(self)
if obj_id in memo:
return memo[obj_id]
new_employee = Employee(
name=self.name,
employee_id=self.employee_id
)
memo[obj_id] = new_employee
if self.department:
new_employee.department = copy.deepcopy(self.department, memo)
if self.manager:
new_employee.manager = copy.deepcopy(self.manager, memo)
new_employee.subordinates = [
copy.deepcopy(sub, memo) for sub in self.subordinates
]
return new_employee
def add_subordinate(self, employee: 'Employee') -> None:
employee.manager = self
self.subordinates.append(employee)
def __repr__(self) -> str:
dept_name = self.department.name if self.department else "无部门"
sub_count = len(self.subordinates)
return f"Employee({self.name}, dept={dept_name}, subs={sub_count})"
@dataclass
class Department:
name: str
manager: Optional[Employee] = None
members: List[Employee] = field(default_factory=list)
def add_member(self, employee: Employee) -> None:
employee.department = self
self.members.append(employee)
def __deepcopy__(self, memo: dict) -> 'Department':
obj_id = id(self)
if obj_id in memo:
return memo[obj_id]
new_dept = Department(name=self.name)
memo[obj_id] = new_dept
if self.manager:
new_dept.manager = copy.deepcopy(self.manager, memo)
new_dept.members = [
copy.deepcopy(member, memo) for member in self.members
]
return new_dept
def demo_circular_reference():
dept = Department("研发部")
manager = Employee("张经理", "E001")
dept.manager = manager
manager.department = dept
emp1 = Employee("李工程师", "E002")
emp2 = Employee("王工程师", "E003")
dept.add_member(manager)
dept.add_member(emp1)
dept.add_member(emp2)
manager.add_subordinate(emp1)
manager.add_subordinate(emp2)
print("原始组织结构:")
print(f" 部门: {dept.name}")
print(f" 经理: {manager.name}")
print(f" 成员: {[m.name for m in dept.members]}")
dept_clone = copy.deepcopy(dept)
print("\n克隆组织结构:")
print(f" 部门: {dept_clone.name}")
print(f" 经理: {dept_clone.manager.name if dept_clone.manager else 'None'}")
print(f" 成员: {[m.name for m in dept_clone.members]}")
print("\n验证独立性:")
print(f" 原始部门ID: {id(dept)}")
print(f" 克隆部门ID: {id(dept_clone)}")
print(f" 原始经理部门ID: {id(manager.department)}")
print(f" 克隆经理部门ID: {id(dept_clone.manager.department)}")
print(f" 循环引用正确: {id(dept_clone) == id(dept_clone.manager.department)}")
demo_circular_reference()5.3.2 不可变对象克隆
from dataclasses import dataclass, field, replace
from typing import Tuple, FrozenSet, Optional
import copy
@dataclass(frozen=True)
class ImmutablePoint:
"""不可变坐标点"""
x: float
y: float
def translate(self, dx: float, dy: float) -> 'ImmutablePoint':
return ImmutablePoint(self.x + dx, self.y + dy)
def __copy__(self) -> 'ImmutablePoint':
return self
def __deepcopy__(self, memo: dict) -> 'ImmutablePoint':
return self
@dataclass(frozen=True)
class ImmutableRectangle:
"""不可变矩形"""
top_left: ImmutablePoint
width: float
height: float
color: str = "black"
@property
def bottom_right(self) -> ImmutablePoint:
return ImmutablePoint(
self.top_left.x + self.width,
self.top_left.y + self.height
)
@property
def area(self) -> float:
return self.width * self.height
def with_color(self, new_color: str) -> 'ImmutableRectangle':
return replace(self, color=new_color)
def with_size(self, width: float, height: float) -> 'ImmutableRectangle':
return replace(self, width=width, height=height)
def move(self, dx: float, dy: float) -> 'ImmutableRectangle':
return replace(self, top_left=self.top_left.translate(dx, dy))
def __copy__(self) -> 'ImmutableRectangle':
return self
def __deepcopy__(self, memo: dict) -> 'ImmutableRectangle':
return self
@dataclass(frozen=True)
class ImmutableDocument:
"""不可变文档"""
title: str
content: str
author: str
tags: Tuple[str, ...] = ()
version: int = 1
def with_title(self, new_title: str) -> 'ImmutableDocument':
return replace(self, title=new_title, version=self.version + 1)
def with_content(self, new_content: str) -> 'ImmutableDocument':
return replace(self, content=new_content, version=self.version + 1)
def add_tag(self, tag: str) -> 'ImmutableDocument':
new_tags = self.tags + (tag,)
return replace(self, tags=new_tags, version=self.version + 1)
def __copy__(self) -> 'ImmutableDocument':
return self
def __deepcopy__(self, memo: dict) -> 'ImmutableDocument':
return self
def demo_immutable_clone():
rect = ImmutableRectangle(
top_left=ImmutablePoint(10, 20),
width=100,
height=50,
color="red"
)
print(f"原始矩形: {rect}")
print(f"面积: {rect.area}")
moved = rect.move(5, 5)
print(f"移动后: {moved}")
print(f"原始不变: {rect}")
recolored = rect.with_color("blue")
print(f"改色后: {recolored}")
doc = ImmutableDocument(
title="设计模式",
content="原型模式",
author="张三",
tags=("设计模式",)
)
print(f"\n原始文档: {doc}")
updated = doc.add_tag("创建型模式").with_content("更新内容")
print(f"更新文档: {updated}")
print(f"版本变化: {doc.version} → {updated.version}")
print("\n不可变对象克隆优化:")
print(f" copy.copy与原对象相同: {copy.copy(rect) is rect}")
print(f" copy.deepcopy与原对象相同: {copy.deepcopy(rect) is rect}")
demo_immutable_clone()5.3.3 带验证的克隆
from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Optional, TypeVar, Generic
from abc import ABC, abstractmethod
import copy
T = TypeVar('T')
class CloneValidator(ABC):
"""克隆验证器抽象基类"""
@abstractmethod
def validate(self, original: Any, clone: Any) -> bool:
"""验证克隆是否有效"""
pass
@abstractmethod
def get_errors(self) -> List[str]:
"""获取验证错误"""
pass
class DataIntegrityValidator(CloneValidator):
"""数据完整性验证器"""
def __init__(self):
self._errors: List[str] = []
def validate(self, original: Any, clone: Any) -> bool:
self._errors.clear()
if type(original) != type(clone):
self._errors.append(f"类型不匹配: {type(original)} vs {type(clone)}")
if original is clone:
self._errors.append("克隆与原对象是同一实例")
return len(self._errors) == 0
def get_errors(self) -> List[str]:
return self._errors.copy()
class FieldEqualityValidator(CloneValidator):
"""字段相等性验证器"""
def __init__(self, fields: List[str]):
self.fields = fields
self._errors: List[str] = []
def validate(self, original: Any, clone: Any) -> bool:
self._errors.clear()
for field_name in self.fields:
if not hasattr(original, field_name):
continue
orig_value = getattr(original, field_name)
clone_value = getattr(clone, field_name, None)
if orig_value != clone_value:
self._errors.append(
f"字段 '{field_name}' 值不匹配: {orig_value} vs {clone_value}"
)
return len(self._errors) == 0
def get_errors(self) -> List[str]:
return self._errors.copy()
@dataclass
class ValidatedPrototype:
"""
带验证的原型基类
在克隆后自动执行验证,确保数据完整性
"""
_validators: List[CloneValidator] = field(default_factory=list, repr=False)
_clone_hooks: List[Callable[[Any], None]] = field(default_factory=list, repr=False)
def add_validator(self, validator: CloneValidator) -> 'ValidatedPrototype':
self._validators.append(validator)
return self
def add_clone_hook(self, hook: Callable[[Any], None]) -> 'ValidatedPrototype':
self._clone_hooks.append(hook)
return self
def clone_with_validation(self, deep: bool = True) -> tuple['ValidatedPrototype', List[str]]:
"""
执行带验证的克隆
Returns:
(克隆对象, 验证错误列表)
"""
if deep:
clone = copy.deepcopy(self)
else:
clone = copy.copy(self)
clone._validators = self._validators.copy()
clone._clone_hooks = self._clone_hooks.copy()
errors = []
for validator in self._validators:
if not validator.validate(self, clone):
errors.extend(validator.get_errors())
for hook in self._clone_hooks:
hook(clone)
return clone, errors
@dataclass
class BankAccount(ValidatedPrototype):
"""银行账户,展示带验证的克隆"""
account_number: str = ""
owner: str = ""
balance: float = 0.0
currency: str = "CNY"
is_active: bool = True
def __post_init__(self):
integrity_validator = DataIntegrityValidator()
field_validator = FieldEqualityValidator(
['account_number', 'owner', 'currency']
)
self.add_validator(integrity_validator)
self.add_validator(field_validator)
def deposit(self, amount: float) -> None:
if amount > 0:
self.balance += amount
def withdraw(self, amount: float) -> bool:
if 0 < amount <= self.balance:
self.balance -= amount
return True
return False
def __deepcopy__(self, memo: dict) -> 'BankAccount':
new_account = BankAccount(
account_number=self.account_number,
owner=self.owner,
balance=self.balance,
currency=self.currency,
is_active=self.is_active
)
new_account._validators = self._validators.copy()
new_account._clone_hooks = self._clone_hooks.copy()
memo[id(self)] = new_account
return new_account
def demo_validated_clone():
account = BankAccount(
account_number="1234567890",
owner="张三",
balance=10000.0,
currency="CNY"
)
print(f"原始账户: {account.owner}, 余额: {account.balance}")
clone, errors = account.clone_with_validation()
print(f"\n克隆结果:")
print(f" 克隆账户: {clone.owner}, 余额: {clone.balance}")
print(f" 验证通过: {len(errors) == 0}")
if errors:
print(f" 错误: {errors}")
clone.deposit(5000)
print(f"\n克隆账户存款后:")
print(f" 原始余额: {account.balance}")
print(f" 克隆余额: {clone.balance}")
demo_validated_clone()5.4 企业级应用示例
5.4.1 数据库连接池原型
from dataclasses import dataclass, field
from typing import Dict, Any, Optional, List, Callable
from enum import Enum
import copy
import time
class DatabaseType(Enum):
POSTGRESQL = "postgresql"
MYSQL = "mysql"
SQLITE = "sqlite"
ORACLE = "oracle"
@dataclass
class ConnectionConfig:
"""数据库连接配置"""
host: str = "localhost"
port: int = 5432
database: str = ""
username: str = ""
password: str = ""
pool_size: int = 5
timeout: int = 30
ssl_enabled: bool = False
ssl_cert: Optional[str] = None
def clone(self, **overrides) -> 'ConnectionConfig':
new_config = copy.deepcopy(self)
for key, value in overrides.items():
if hasattr(new_config, key):
setattr(new_config, key, value)
return new_config
@property
def connection_string(self) -> str:
if self.host == ":memory:":
return f"sqlite:///{self.database}"
auth = f"{self.username}:{self.password}@" if self.username else ""
return f"{self.database_type.value}://{auth}{self.host}:{self.port}/{self.database}"
@property
def database_type(self) -> DatabaseType:
return DatabaseType.POSTGRESQL
@dataclass
class ConnectionPool:
"""数据库连接池"""
config: ConnectionConfig
_connections: List[Any] = field(default_factory=list, repr=False)
_available: List[int] = field(default_factory=list, repr=False)
_in_use: Dict[int, float] = field(default_factory=dict, repr=False)
created_at: float = field(default_factory=time.time)
def acquire(self) -> int:
"""获取连接"""
if self._available:
conn_id = self._available.pop()
self._in_use[conn_id] = time.time()
return conn_id
if len(self._connections) < self.config.pool_size:
conn_id = len(self._connections)
self._connections.append(self._create_connection())
self._in_use[conn_id] = time.time()
return conn_id
raise RuntimeError("连接池已满")
def release(self, conn_id: int) -> None:
"""释放连接"""
if conn_id in self._in_use:
del self._in_use[conn_id]
self._available.append(conn_id)
def _create_connection(self) -> dict:
"""模拟创建连接"""
return {
"id": len(self._connections),
"config": self.config.connection_string,
"created": time.time()
}
def clone(self) -> 'ConnectionPool':
"""
克隆连接池
注意:不克隆活跃连接,仅复制配置
"""
new_pool = ConnectionPool(
config=copy.deepcopy(self.config),
created_at=time.time()
)
return new_pool
@property
def stats(self) -> Dict[str, Any]:
return {
"total": len(self._connections),
"available": len(self._available),
"in_use": len(self._in_use),
"pool_size": self.config.pool_size
}
class ConnectionPoolPrototypeFactory:
"""连接池原型工厂"""
def __init__(self):
self._prototypes: Dict[str, ConnectionPool] = {}
self._setup_default_prototypes()
def _setup_default_prototypes(self) -> None:
dev_config = ConnectionConfig(
host="localhost",
port=5432,
database="dev_db",
username="dev_user",
password="dev_pass",
pool_size=3,
timeout=10
)
self._prototypes["development"] = ConnectionPool(dev_config)
staging_config = ConnectionConfig(
host="staging-db.internal",
port=5432,
database="staging_db",
username="staging_user",
password="staging_pass",
pool_size=10,
timeout=30,
ssl_enabled=True
)
self._prototypes["staging"] = ConnectionPool(staging_config)
prod_config = ConnectionConfig(
host="prod-db.internal",
port=5432,
database="prod_db",
username="prod_user",
password="prod_pass",
pool_size=20,
timeout=60,
ssl_enabled=True,
ssl_cert="/etc/ssl/db-cert.pem"
)
self._prototypes["production"] = ConnectionPool(prod_config)
test_config = ConnectionConfig(
host=":memory:",
database=":memory:",
pool_size=1,
timeout=5
)
self._prototypes["testing"] = ConnectionPool(test_config)
def create_pool(
self,
environment: str,
**config_overrides
) -> ConnectionPool:
"""创建连接池实例"""
if environment not in self._prototypes:
raise ValueError(f"未知环境: {environment}")
prototype = self._prototypes[environment]
if config_overrides:
new_config = prototype.config.clone(**config_overrides)
new_pool = ConnectionPool(new_config)
else:
new_pool = prototype.clone()
return new_pool
def list_environments(self) -> List[str]:
return list(self._prototypes.keys())
def demo_connection_pool_prototype():
factory = ConnectionPoolPrototypeFactory()
print("可用环境:", factory.list_environments())
dev_pool = factory.create_pool("development")
print(f"\n开发环境连接池:")
print(f" 配置: {dev_pool.config.host}:{dev_pool.config.port}")
print(f" 池大小: {dev_pool.config.pool_size}")
conn1 = dev_pool.acquire()
conn2 = dev_pool.acquire()
print(f" 获取连接后: {dev_pool.stats}")
dev_pool.release(conn1)
print(f" 释放连接后: {dev_pool.stats}")
custom_pool = factory.create_pool(
"production",
pool_size=50,
timeout=120
)
print(f"\n自定义生产环境连接池:")
print(f" 池大小: {custom_pool.config.pool_size}")
print(f" 超时: {custom_pool.config.timeout}")
demo_connection_pool_prototype()5.4.2 游戏实体原型系统
from dataclasses import dataclass, field
from typing import Dict, List, Any, Optional, Callable, TypeVar
from abc import ABC, abstractmethod
from enum import Enum
import copy
class EntityType(Enum):
PLAYER = "player"
ENEMY = "enemy"
NPC = "npc"
ITEM = "item"
PROJECTILE = "projectile"
@dataclass
class Stat:
"""属性值"""
base: float
current: float = None
def __post_init__(self):
if self.current is None:
self.current = self.base
@property
def ratio(self) -> float:
return self.current / self.base if self.base > 0 else 0
def modify(self, amount: float) -> None:
self.current = max(0, min(self.base, self.current + amount))
def reset(self) -> None:
self.current = self.base
@dataclass
class Skill:
"""技能"""
name: str
damage: float
mana_cost: float
cooldown: float
current_cooldown: float = 0
def is_ready(self) -> bool:
return self.current_cooldown <= 0
def use(self) -> bool:
if self.is_ready():
self.current_cooldown = self.cooldown
return True
return False
def tick(self, dt: float) -> None:
self.current_cooldown = max(0, self.current_cooldown - dt)
@dataclass
class Equipment:
"""装备"""
name: str
slot: str
stat_bonuses: Dict[str, float] = field(default_factory=dict)
special_effects: List[str] = field(default_factory=list)
class GameEntity(ABC):
"""游戏实体抽象基类"""
def __init__(
self,
name: str,
entity_type: EntityType,
level: int = 1
):
self.name = name
self.entity_type = entity_type
self.level = level
self.stats: Dict[str, Stat] = {}
self.skills: List[Skill] = []
self.equipment: Dict[str, Equipment] = {}
self.tags: List[str] = []
self._position: tuple = (0, 0)
@abstractmethod
def clone(self) -> 'GameEntity':
pass
def set_position(self, x: float, y: float) -> None:
self._position = (x, y)
@property
def position(self) -> tuple:
return self._position
def add_stat(self, name: str, base: float) -> None:
self.stats[name] = Stat(base)
def get_stat(self, name: str) -> Optional[Stat]:
return self.stats.get(name)
def learn_skill(self, skill: Skill) -> None:
self.skills.append(skill)
def equip(self, item: Equipment) -> None:
self.equipment[item.slot] = item
for stat_name, bonus in item.stat_bonuses.items():
if stat_name in self.stats:
self.stats[stat_name].base += bonus
def __deepcopy__(self, memo: dict) -> 'GameEntity':
cls = self.__class__
new_entity = cls.__new__(cls)
memo[id(self)] = new_entity
new_entity.name = self.name
new_entity.entity_type = self.entity_type
new_entity.level = self.level
new_entity.stats = copy.deepcopy(self.stats, memo)
new_entity.skills = copy.deepcopy(self.skills, memo)
new_entity.equipment = copy.deepcopy(self.equipment, memo)
new_entity.tags = self.tags.copy()
new_entity._position = self._position
return new_entity
class Character(GameEntity):
"""角色实体"""
def __init__(
self,
name: str,
entity_type: EntityType,
level: int = 1,
character_class: str = "warrior"
):
super().__init__(name, entity_type, level)
self.character_class = character_class
self.experience: int = 0
self.inventory: List[str] = []
def clone(self) -> 'Character':
return copy.deepcopy(self)
def gain_experience(self, amount: int) -> bool:
self.experience += amount
threshold = self.level * 100
if self.experience >= threshold:
self.level_up()
return True
return False
def level_up(self) -> None:
self.level += 1
self.experience = 0
for stat in self.stats.values():
stat.base = int(stat.base * 1.1)
stat.reset()
class Enemy(GameEntity):
"""敌人实体"""
def __init__(
self,
name: str,
level: int = 1,
ai_type: str = "aggressive"
):
super().__init__(name, EntityType.ENEMY, level)
self.ai_type = ai_type
self.loot_table: Dict[str, float] = {}
self.aggro_range: float = 10.0
def clone(self) -> 'Enemy':
return copy.deepcopy(self)
def set_loot(self, item: str, chance: float) -> None:
self.loot_table[item] = chance
class EntityPrototypeFactory:
"""实体原型工厂"""
def __init__(self):
self._prototypes: Dict[str, GameEntity] = {}
self._setup_default_prototypes()
def _setup_default_prototypes(self) -> None:
warrior = Character(
name="战士",
entity_type=EntityType.PLAYER,
level=1,
character_class="warrior"
)
warrior.add_stat("hp", 150)
warrior.add_stat("mp", 30)
warrior.add_stat("attack", 15)
warrior.add_stat("defense", 10)
warrior.learn_skill(Skill("猛击", 25, 10, 3.0))
self._prototypes["warrior"] = warrior
mage = Character(
name="法师",
entity_type=EntityType.PLAYER,
level=1,
character_class="mage"
)
mage.add_stat("hp", 80)
mage.add_stat("mp", 100)
mage.add_stat("attack", 5)
mage.add_stat("defense", 3)
mage.learn_skill(Skill("火球术", 35, 20, 2.5))
mage.learn_skill(Skill("冰霜新星", 25, 15, 3.0))
self._prototypes["mage"] = mage
goblin = Enemy(name="哥布林", level=1, ai_type="aggressive")
goblin.add_stat("hp", 30)
goblin.add_stat("attack", 8)
goblin.add_stat("defense", 2)
goblin.aggro_range = 5.0
goblin.set_loot("金币", 0.8)
goblin.set_loot("破旧匕首", 0.2)
self._prototypes["goblin"] = goblin
dragon = Enemy(name="幼龙", level=10, ai_type="boss")
dragon.add_stat("hp", 500)
dragon.add_stat("attack", 50)
dragon.add_stat("defense", 20)
dragon.aggro_range = 15.0
dragon.learn_skill(Skill("火焰吐息", 80, 0, 5.0))
dragon.set_loot("龙鳞", 1.0)
dragon.set_loot("龙之心", 0.1)
self._prototypes["dragon"] = dragon
def create(self, prototype_name: str, custom_name: str = None) -> GameEntity:
"""创建实体实例"""
if prototype_name not in self._prototypes:
raise ValueError(f"未知原型: {prototype_name}")
entity = self._prototypes[prototype_name].clone()
if custom_name:
entity.name = custom_name
return entity
def create_batch(
self,
prototype_name: str,
count: int
) -> List[GameEntity]:
"""批量创建实体"""
return [self.create(prototype_name) for _ in range(count)]
def list_prototypes(self) -> Dict[str, str]:
return {
name: f"{proto.name} (Lv.{proto.level})"
for name, proto in self._prototypes.items()
}
def demo_game_entity_prototype():
factory = EntityPrototypeFactory()
print("可用原型:")
for name, desc in factory.list_prototypes().items():
print(f" {name}: {desc}")
player = factory.create("warrior", "阿瑟王")
player.equip(Equipment("铁剑", "weapon", {"attack": 10}))
player.set_position(100, 200)
print(f"\n玩家: {player.name}")
print(f" 职业: {player.character_class}")
print(f" 等级: {player.level}")
print(f" HP: {player.get_stat('hp').current}/{player.get_stat('hp').base}")
print(f" 攻击力: {player.get_stat('attack').base}")
print(f" 位置: {player.position}")
enemies = factory.create_batch("goblin", 3)
for i, enemy in enumerate(enemies):
enemy.set_position(i * 10, i * 10)
print(f"\n敌人{i+1}: {enemy.name}")
print(f" HP: {enemy.get_stat('hp').base}")
print(f" 位置: {enemy.position}")
boss = factory.create("dragon")
print(f"\nBoss: {boss.name}")
print(f" HP: {boss.get_stat('hp').base}")
print(f" 技能: {[s.name for s in boss.skills]}")
print(f" 掉落: {list(boss.loot_table.keys())}")
demo_game_entity_prototype()5.4.3 消息模板原型
from dataclasses import dataclass, field
from typing import Dict, List, Any, Optional, Callable
from enum import Enum
import copy
import re
from datetime import datetime
class MessageChannel(Enum):
EMAIL = "email"
SMS = "sms"
PUSH = "push"
WEBHOOK = "webhook"
@dataclass
class MessageVariable:
"""消息变量定义"""
name: str
description: str
required: bool = True
default: Any = None
validator: Optional[Callable[[Any], bool]] = None
@dataclass
class MessageTemplate:
"""消息模板"""
name: str
channel: MessageChannel
subject_template: str
body_template: str
variables: Dict[str, MessageVariable] = field(default_factory=dict)
metadata: Dict[str, Any] = field(default_factory=dict)
version: int = 1
created_at: datetime = field(default_factory=datetime.now)
def add_variable(
self,
name: str,
description: str,
required: bool = True,
default: Any = None,
validator: Callable[[Any], bool] = None
) -> 'MessageTemplate':
self.variables[name] = MessageVariable(
name, description, required, default, validator
)
return self
def validate_variables(self, values: Dict[str, Any]) -> List[str]:
"""验证变量值"""
errors = []
for name, var in self.variables.items():
if var.required and name not in values:
if var.default is None:
errors.append(f"缺少必填变量: {name}")
continue
value = values.get(name, var.default)
if var.validator and value is not None:
if not var.validator(value):
errors.append(f"变量 '{name}' 值无效: {value}")
return errors
def render(self, **values) -> Dict[str, str]:
"""渲染模板"""
errors = self.validate_variables(values)
if errors:
raise ValueError("\n".join(errors))
merged_values = {}
for name, var in self.variables.items():
merged_values[name] = values.get(name, var.default)
subject = self._render_string(self.subject_template, merged_values)
body = self._render_string(self.body_template, merged_values)
return {"subject": subject, "body": body}
def _render_string(self, template: str, values: Dict[str, Any]) -> str:
"""渲染字符串模板"""
result = template
for key, value in values.items():
result = result.replace(f"{{{key}}}", str(value))
return result
def clone(self, new_name: str = None) -> 'MessageTemplate':
"""克隆模板"""
new_template = copy.deepcopy(self)
if new_name:
new_template.name = new_name
new_template.version = 1
new_template.created_at = datetime.now()
return new_template
class MessageTemplateRegistry:
"""消息模板注册表"""
def __init__(self):
self._templates: Dict[str, MessageTemplate] = {}
self._setup_default_templates()
def _setup_default_templates(self) -> None:
welcome = MessageTemplate(
name="欢迎邮件",
channel=MessageChannel.EMAIL,
subject_template="欢迎加入 {company_name}!",
body_template="""
亲爱的 {username}:
欢迎加入 {company_name}!您的账户已成功创建。
登录信息:
- 用户名:{username}
- 初始密码:{initial_password}
请尽快登录并修改密码。
此致
{company_name} 团队
""".strip()
)
welcome.add_variable("company_name", "公司名称")
welcome.add_variable("username", "用户名")
welcome.add_variable("initial_password", "初始密码")
self._templates["welcome_email"] = welcome
order_confirm = MessageTemplate(
name="订单确认",
channel=MessageChannel.EMAIL,
subject_template="订单确认 - {order_id}",
body_template="""
尊敬的 {customer_name}:
您的订单已确认!
订单编号:{order_id}
订单金额:{order_amount} 元
预计送达:{delivery_date}
收货地址:
{shipping_address}
感谢您的购买!
""".strip()
)
order_confirm.add_variable("order_id", "订单编号")
order_confirm.add_variable("customer_name", "客户姓名")
order_confirm.add_variable("order_amount", "订单金额")
order_confirm.add_variable("delivery_date", "送达日期")
order_confirm.add_variable("shipping_address", "收货地址")
self._templates["order_confirmation"] = order_confirm
alert = MessageTemplate(
name="系统告警",
channel=MessageChannel.SMS,
subject_template="系统告警",
body_template="【{system_name}】{alert_level}告警:{alert_message}。时间:{alert_time}"
)
alert.add_variable("system_name", "系统名称")
alert.add_variable("alert_level", "告警级别")
alert.add_variable("alert_message", "告警信息")
alert.add_variable("alert_time", "告警时间")
self._templates["system_alert"] = alert
password_reset = MessageTemplate(
name="密码重置",
channel=MessageChannel.EMAIL,
subject_template="密码重置请求",
body_template="""
尊敬的用户:
我们收到了您的密码重置请求。
验证码:{verification_code}
有效期:{expiry_minutes} 分钟
如果您没有发起此请求,请忽略此邮件。
""".strip()
)
password_reset.add_variable("verification_code", "验证码")
password_reset.add_variable("expiry_minutes", "有效期(分钟)", default=30)
self._templates["password_reset"] = password_reset
def register(self, key: str, template: MessageTemplate) -> None:
self._templates[key] = template
def get_template(self, key: str) -> MessageTemplate:
if key not in self._templates:
raise KeyError(f"模板 '{key}' 不存在")
return self._templates[key]
def render(self, template_key: str, **values) -> Dict[str, str]:
template = self.get_template(template_key)
return template.render(**values)
def create_custom(
self,
base_key: str,
new_key: str,
overrides: Dict[str, str] = None
) -> MessageTemplate:
"""基于现有模板创建自定义模板"""
base = self.get_template(base_key)
custom = base.clone(new_name=f"自定义_{base.name}")
if overrides:
if "subject" in overrides:
custom.subject_template = overrides["subject"]
if "body" in overrides:
custom.body_template = overrides["body"]
self._templates[new_key] = custom
return custom
def list_templates(self) -> Dict[str, Dict[str, Any]]:
return {
key: {
"name": t.name,
"channel": t.channel.value,
"variables": list(t.variables.keys())
}
for key, t in self._templates.items()
}
def demo_message_template():
registry = MessageTemplateRegistry()
print("已注册模板:")
for key, info in registry.list_templates().items():
print(f" {key}: {info['name']} ({info['channel']})")
welcome_msg = registry.render(
"welcome_email",
company_name="科技有限公司",
username="zhangsan",
initial_password="Temp@12345"
)
print(f"\n欢迎邮件:")
print(f" 主题: {welcome_msg['subject']}")
print(f" 正文:\n{welcome_msg['body']}")
alert_msg = registry.render(
"system_alert",
system_name="订单系统",
alert_level="严重",
alert_message="数据库连接池已满",
alert_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
)
print(f"\n告警短信:")
print(f" {alert_msg['body']}")
custom = registry.create_custom(
"welcome_email",
"vip_welcome",
{"subject": "尊贵的VIP会员欢迎加入 {company_name}!"}
)
print(f"\n自定义模板: {custom.name}")
demo_message_template()5.5 深拷贝与浅拷贝深度分析
5.5.1 内存模型对比
┌─────────────────────────────────────────────────────────────┐
│ 浅拷贝 vs 深拷贝 │
│ 内存模型对比 │
└─────────────────────────────────────────────────────────────┘
原始对象结构:
┌─────────────────────────────────────────────────────────────┐
│ obj = { │
│ 'name': 'Alice', # 不可变对象 (str) │
│ 'scores': [85, 90, 78], # 可变对象 │
│ 'profile': { # 可变对象 │
│ 'age': 25, │
│ 'city': 'Beijing' │
│ } │
│ } │
└─────────────────────────────────────────────────────────────┘
浅拷贝后:
┌───────────────────┐ ┌───────────────────┐
│ original │ │ shallow_copy │
│ ──────────── │ │ ──────────── │
│ name: 'Alice' ◄──┼──┬──┼──► name: 'Alice' │ (共享不可变)
│ scores ──────────┼──┼──┼───────────────────┘
│ profile ─────────┼──┼──┼───────────────────┐
└───────────────────┘ │ │ │ │
│ │ │ │
▼ │ ▼ │
┌────────────┴────────────┐ │
│ scores列表 │ │
│ [85, 90, 78] │ │
│ (两个对象共享) │ │
└─────────────────────────┘ │
│
┌───────────────────────┘
▼
┌─────────────────────────┐
│ profile字典 │
│ {'age': 25, ...} │
│ (两个对象共享) │
└─────────────────────────┘
深拷贝后:
┌───────────────────┐ ┌───────────────────┐
│ original │ │ deep_copy │
│ ──────────── │ │ ──────────── │
│ name: 'Alice' ◄──┼──┬──┼──► name: 'Alice' │ (共享不可变)
│ scores ──────────┼──┤ │ scores ──────────┼──┐
│ profile ─────────┼──┤ │ profile ─────────┼──┼──┐
└───────────────────┘ │ └───────────────────┘ │ │
│ │ │
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐
│ original │ │ deep_copy │
│ scores列表 │ │ scores列表 │
│ [85, 90, 78] │ │ [85, 90, 78] │
└────────────────┘ └────────────────┘
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ original │ │ deep_copy │
│ profile字典 │ │ profile字典 │
└────────────────┘ └────────────────┘5.5.2 性能考量与优化策略
import copy
import time
from dataclasses import dataclass, field
from typing import List, Dict, Any
import json
@dataclass
class PerformanceTestObject:
"""性能测试对象"""
id: int
name: str
values: List[int] = field(default_factory=list)
metadata: Dict[str, Any] = field(default_factory=dict)
class ClonePerformanceAnalyzer:
"""克隆性能分析器"""
@staticmethod
def create_test_object(
list_size: int = 1000,
dict_size: int = 100
) -> PerformanceTestObject:
return PerformanceTestObject(
id=1,
name="test_object",
values=list(range(list_size)),
metadata={f"key_{i}": f"value_{i}" for i in range(dict_size)}
)
@staticmethod
def benchmark_shallow_copy(obj: Any, iterations: int = 10000) -> float:
start = time.perf_counter()
for _ in range(iterations):
copy.copy(obj)
return time.perf_counter() - start
@staticmethod
def benchmark_deep_copy(obj: Any, iterations: int = 10000) -> float:
start = time.perf_counter()
for _ in range(iterations):
copy.deepcopy(obj)
return time.perf_counter() - start
@staticmethod
def benchmark_json_copy(obj: Any, iterations: int = 10000) -> float:
start = time.perf_counter()
for _ in range(iterations):
json.loads(json.dumps(obj))
return time.perf_counter() - start
@classmethod
def run_analysis(cls, iterations: int = 1000) -> Dict[str, Any]:
obj = cls.create_test_object()
shallow_time = cls.benchmark_shallow_copy(obj, iterations)
deep_time = cls.benchmark_deep_copy(obj, iterations)
obj_dict = {
'id': obj.id,
'name': obj.name,
'values': obj.values,
'metadata': obj.metadata
}
json_time = cls.benchmark_json_copy(obj_dict, iterations)
return {
'iterations': iterations,
'shallow_copy': shallow_time,
'deep_copy': deep_time,
'json_copy': json_time,
'deep_vs_shallow_ratio': deep_time / shallow_time if shallow_time > 0 else 0,
'json_vs_deep_ratio': json_time / deep_time if deep_time > 0 else 0
}
class OptimizedCloneStrategy:
"""优化克隆策略"""
@staticmethod
def selective_deep_copy(obj: Any, deep_fields: set) -> Any:
"""
选择性深拷贝
仅对指定字段执行深拷贝,其他字段浅拷贝
"""
shallow = copy.copy(obj)
for field_name in deep_fields:
if hasattr(obj, field_name):
value = getattr(obj, field_name)
setattr(shallow, field_name, copy.deepcopy(value))
return shallow
@staticmethod
def copy_on_write(original: Any) -> tuple:
"""
写时复制模式
返回原始对象和写标志,实际复制延迟到修改时
"""
class CopyOnWriteProxy:
def __init__(self, source: Any):
self._source = source
self._copy = None
self._copied = False
def _ensure_copy(self):
if not self._copied:
self._copy = copy.deepcopy(self._source)
self._copied = True
def __getattr__(self, name):
if self._copied:
return getattr(self._copy, name)
return getattr(self._source, name)
def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name, value)
else:
self._ensure_copy()
setattr(self._copy, name, value)
return CopyOnWriteProxy(original), original
def demo_clone_performance():
print("克隆性能分析:")
print("=" * 50)
results = ClonePerformanceAnalyzer.run_analysis(iterations=1000)
print(f"迭代次数: {results['iterations']}")
print(f"浅拷贝耗时: {results['shallow_copy']:.4f}秒")
print(f"深拷贝耗时: {results['deep_copy']:.4f}秒")
print(f"JSON拷贝耗时: {results['json_copy']:.4f}秒")
print(f"深拷贝/浅拷贝比值: {results['deep_vs_shallow_ratio']:.2f}x")
print(f"JSON/深拷贝比值: {results['json_vs_deep_ratio']:.2f}x")
print("\n优化策略演示:")
@dataclass
class SampleObject:
name: str
shallow_field: int
deep_field: List[int]
original = SampleObject(
name="original",
shallow_field=100,
deep_field=[1, 2, 3]
)
optimized = OptimizedCloneStrategy.selective_deep_copy(
original,
deep_fields={'deep_field'}
)
optimized.deep_field.append(4)
print(f"选择性深拷贝后:")
print(f" 原始deep_field: {original.deep_field}")
print(f" 克隆deep_field: {optimized.deep_field}")
demo_clone_performance()5.5.3 选择决策矩阵
| 场景特征 | 浅拷贝 | 深拷贝 | 选择性拷贝 |
|---|---|---|---|
| 对象仅含基本类型 | ✅ 推荐 | ⚠️ 过度 | ❌ 不必要 |
| 对象含可变引用 | ⚠️ 需谨慎 | ✅ 推荐 | ✅ 可选 |
| 需要共享部分状态 | ✅ 推荐 | ❌ 破坏共享 | ✅ 推荐 |
| 性能敏感场景 | ✅ 推荐 | ⚠️ 较慢 | ✅ 平衡 |
| 循环引用存在 | ❌ 可能问题 | ⚠️ 需特殊处理 | ⚠️ 需特殊处理 |
| 不可变对象 | ✅ 推荐 | ✅ 推荐 | ❌ 不必要 |
| 大型嵌套结构 | ✅ 推荐 | ⚠️ 耗时 | ✅ 推荐 |
5.6 与其他创建型模式比较
5.6.1 模式对比分析
┌─────────────────────────────────────────────────────────────┐
│ 创建型模式对比矩阵 │
└─────────────────────────────────────────────────────────────┘
模式 │ 创建方式 │ 关注点 │ 适用场景
──────────────┼───────────────┼───────────────┼─────────────────
单例模式 │ 控制实例数量 │ 唯一性 │ 全局状态、配置
工厂方法 │ 子类决定 │ 扩展性 │ 框架设计
抽象工厂 │ 产品族 │ 一致性 │ 跨平台UI
建造者模式 │ 分步构建 │ 复杂构造 │ 复杂对象
原型模式 │ 复制现有 │ 性能/相似性 │ 成本高、预配置5.6.2 组合使用模式
from abc import ABC, abstractmethod
from typing import Dict, TypeVar, Generic, Optional
from dataclasses import dataclass
import copy
T = TypeVar('T')
class PrototypeFactory(Generic[T]):
"""
原型工厂:结合工厂模式与原型模式
优势:
- 工厂模式提供统一创建接口
- 原型模式提供高效实例化
"""
def __init__(self):
self._prototypes: Dict[str, T] = {}
def register_prototype(self, name: str, prototype: T) -> None:
self._prototypes[name] = prototype
def create(self, name: str, **overrides) -> T:
if name not in self._prototypes:
raise ValueError(f"未知原型: {name}")
instance = copy.deepcopy(self._prototypes[name])
for key, value in overrides.items():
if hasattr(instance, key):
setattr(instance, key, value)
return instance
@dataclass
class DatabaseConnection:
host: str
port: int
database: str
username: str = ""
password: str = ""
def connect(self) -> str:
return f"Connected to {self.host}:{self.port}/{self.database}"
class ConnectionBuilder:
"""
建造者模式:与原型模式结合
建造者构建原型,原型快速复制
"""
def __init__(self):
self._host = "localhost"
self._port = 5432
self._database = ""
self._username = ""
self._password = ""
def host(self, host: str) -> 'ConnectionBuilder':
self._host = host
return self
def port(self, port: int) -> 'ConnectionBuilder':
self._port = port
return self
def database(self, database: str) -> 'ConnectionBuilder':
self._database = database
return self
def credentials(self, username: str, password: str) -> 'ConnectionBuilder':
self._username = username
self._password = password
return self
def build(self) -> DatabaseConnection:
return DatabaseConnection(
host=self._host,
port=self._port,
database=self._database,
username=self._username,
password=self._password
)
def build_prototype(self, factory: PrototypeFactory, name: str) -> None:
prototype = self.build()
factory.register_prototype(name, prototype)
def demo_combined_patterns():
factory = PrototypeFactory[DatabaseConnection]()
builder = ConnectionBuilder()
builder.host("prod-db.internal").port(5432).database("app_db")
builder.build_prototype(factory, "production")
builder = ConnectionBuilder()
builder.host("localhost").port(5432).database("dev_db")
builder.build_prototype(factory, "development")
prod_conn = factory.create("production", username="admin")
dev_conn = factory.create("development", username="dev_user")
print(f"生产连接: {prod_conn.connect()}")
print(f"开发连接: {dev_conn.connect()}")
print(f"\n从同一原型创建多个实例:")
for i in range(3):
conn = factory.create("development", database=f"test_db_{i}")
print(f" 实例{i+1}: {conn.database}")
demo_combined_patterns()5.7 反模式与最佳实践
5.7.1 常见反模式
import copy
from typing import Any
class PrototypeAntiPatterns:
"""原型模式反模式示例"""
@staticmethod
def anti_pattern_1_shallow_copy_mutation():
"""
反模式:浅拷贝后修改共享引用
问题:浅拷贝共享可变对象,修改影响原对象
"""
original = {
'name': 'Alice',
'scores': [85, 90, 78]
}
shallow = copy.copy(original)
shallow['scores'].append(95)
print("反模式1:浅拷贝修改共享引用")
print(f" 原始scores: {original['scores']}")
print(f" 问题:原对象被意外修改!")
@staticmethod
def anti_pattern_2_missing_deepcopy():
"""
反模式:需要深拷贝时使用浅拷贝
"""
class NestedObject:
def __init__(self):
self.data = {'key': 'value'}
class Container:
def __init__(self):
self.nested = NestedObject()
def clone_wrong(self):
return copy.copy(self)
def clone_correct(self):
return copy.deepcopy(self)
original = Container()
wrong_clone = original.clone_wrong()
wrong_clone.nested.data['key'] = 'modified'
print("\n反模式2:需要深拷贝时使用浅拷贝")
print(f" 原始data: {original.nested.data}")
print(f" 问题:嵌套对象被意外修改!")
@staticmethod
def anti_pattern_3_clone_without_reset():
"""
反模式:克隆后未重置状态
"""
class Entity:
def __init__(self, name: str):
self.name = name
self._id = id(self)
self._created_at = "2024-01-01"
def clone_wrong(self) -> 'Entity':
return copy.deepcopy(self)
def clone_correct(self) -> 'Entity':
new_entity = copy.deepcopy(self)
new_entity._id = id(new_entity)
new_entity._created_at = "2024-01-02"
return new_entity
original = Entity("template")
wrong_clone = original.clone_wrong()
print("\n反模式3:克隆后未重置状态")
print(f" 原始ID: {original._id}")
print(f" 克隆ID: {wrong_clone._id}")
print(f" 问题:克隆保留了原对象的运行时状态!")
def demo_anti_patterns():
PrototypeAntiPatterns.anti_pattern_1_shallow_copy_mutation()
PrototypeAntiPatterns.anti_pattern_2_missing_deepcopy()
PrototypeAntiPatterns.anti_pattern_3_clone_without_reset()
demo_anti_patterns()5.7.2 最佳实践清单
from dataclasses import dataclass, field
from typing import List, Dict, Any, Optional
from datetime import datetime
import copy
@dataclass
class BestPracticePrototype:
"""
原型模式最佳实践示例
遵循原则:
1. 明确区分浅拷贝与深拷贝语义
2. 重置运行时状态
3. 处理循环引用
4. 提供克隆验证
5. 文档化克隆行为
"""
name: str
value: int
tags: List[str] = field(default_factory=list)
metadata: Dict[str, Any] = field(default_factory=dict)
_id: int = field(default=0, repr=False)
_created_at: Optional[datetime] = field(default=None, repr=False)
def __post_init__(self):
if self._id == 0:
self._id = id(self)
if self._created_at is None:
self._created_at = datetime.now()
def shallow_clone(self) -> 'BestPracticePrototype':
"""
浅拷贝:共享tags和metadata引用
适用场景:
- 需要共享可变数据
- 性能敏感场景
"""
new_obj = copy.copy(self)
new_obj._id = id(new_obj)
new_obj._created_at = datetime.now()
return new_obj
def deep_clone(self) -> 'BestPracticePrototype':
"""
深拷贝:完全独立的副本
适用场景:
- 需要完全独立
- 防止意外修改
"""
new_obj = copy.deepcopy(self)
new_obj._id = id(new_obj)
new_obj._created_at = datetime.now()
return new_obj
def selective_clone(self, deep_fields: set = None) -> 'BestPracticePrototype':
"""
选择性深拷贝:精确控制拷贝深度
Args:
deep_fields: 需要深拷贝的字段名集合
"""
if deep_fields is None:
deep_fields = {'tags', 'metadata'}
new_obj = copy.copy(self)
for field_name in deep_fields:
if hasattr(self, field_name):
value = getattr(self, field_name)
setattr(new_obj, field_name, copy.deepcopy(value))
new_obj._id = id(new_obj)
new_obj._created_at = datetime.now()
return new_obj
def validate_clone(self, clone: 'BestPracticePrototype') -> List[str]:
"""验证克隆有效性"""
errors = []
if type(self) != type(clone):
errors.append(f"类型不匹配: {type(self)} vs {type(clone)}")
if self is clone:
errors.append("克隆与原对象是同一实例")
if self._id == clone._id:
errors.append("克隆未重置ID")
if self.name != clone.name or self.value != clone.value:
errors.append("基本属性值不匹配")
return errors
BEST_PRACTICE_CHECKLIST = """
原型模式最佳实践清单
====================
□ 拷贝语义
├─ 明确区分 shallow_clone() 和 deep_clone()
├─ 文档化每个方法的适用场景
└─ 提供选择性深拷贝选项
□ 状态管理
├─ 克隆后重置运行时状态(ID、时间戳等)
├─ 保留配置状态(名称、值等)
└─ 处理瞬态属性
□ 引用处理
├─ 正确处理循环引用
├─ 使用memo字典防止无限递归
└─ 考虑弱引用场景
□ 验证机制
├─ 实现克隆验证方法
├─ 检查类型一致性
└─ 检查状态完整性
□ 性能优化
├─ 大对象考虑选择性深拷贝
├─ 不可变对象直接返回self
└─ 缓存频繁克隆的对象
□ 接口设计
├─ 实现 __copy__ 和 __deepcopy__ 协议
├─ 支持 copy.copy() 和 copy.deepcopy()
└─ 提供类型提示
"""
def demo_best_practices():
print(BEST_PRACTICE_CHECKLIST)
original = BestPracticePrototype(
name="template",
value=100,
tags=["tag1", "tag2"],
metadata={"key": "value"}
)
shallow = original.shallow_clone()
deep = original.deep_clone()
selective = original.selective_clone({'tags'})
print("\n克隆验证:")
for name, clone in [("浅拷贝", shallow), ("深拷贝", deep), ("选择性", selective)]:
errors = original.validate_clone(clone)
status = "✓ 通过" if not errors else f"✗ 错误: {errors}"
print(f" {name}: {status}")
shallow.tags.append("new_tag")
deep.tags.append("deep_tag")
print("\n修改后共享状态检查:")
print(f" 原始tags: {original.tags}")
print(f" 浅拷贝tags: {shallow.tags} (共享)")
print(f" 深拷贝tags: {deep.tags} (独立)")
demo_best_practices()5.8 决策指南
5.8.1 使用决策树
┌─────────────────────────────────────────────────────────────┐
│ 原型模式使用决策树 │
└─────────────────────────────────────────────────────────────┘
需要创建对象?
│
▼
┌────────────────────────┐
│ 创建成本是否较高? │
│ (计算密集/IO密集) │
└────────────┬───────────┘
│ │
是 否
│ │
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ 使用原型模式 │ │ 是否需要创建 │
└─────────────┘ │ 相似对象? │
└────────┬────────┘
│
┌────────┴────────┐
是 否
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 使用原型模式 │ │ 使用new创建 │
└─────────────┘ └─────────────┘
│
▼
┌────────────────────────┐
│ 对象是否包含 │
│ 可变引用类型? │
└────────────┬───────────┘
│ │
是 否
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 使用深拷贝 │ │ 浅拷贝即可 │
└─────────────┘ └─────────────┘5.8.2 快速参考卡
PROTOTYPE_QUICK_REFERENCE = """
原型模式快速参考
================
┌─────────────────────────────────────────────────────────────┐
│ 核心概念 │
├─────────────────────────────────────────────────────────────┤
│ 通过复制现有对象创建新对象,而非通过new实例化 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Python实现 │
├─────────────────────────────────────────────────────────────┤
│ import copy │
│ │
│ shallow = copy.copy(obj) # 浅拷贝 │
│ deep = copy.deepcopy(obj) # 深拷贝 │
│ │
│ class MyClass: │
│ def __copy__(self): ... # 自定义浅拷贝 │
│ def __deepcopy__(self, memo): ... # 自定义深拷贝 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 适用场景 │
├─────────────────────────────────────────────────────────────┤
│ ✓ 对象创建成本高(数据库查询、网络请求、复杂计算) │
│ ✓ 需要创建大量相似对象 │
│ ✓ 对象结构复杂,手动复制容易出错 │
│ ✓ 运行时动态确定对象类型 │
│ ✓ 需要保存对象状态快照 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 注意事项 │
├─────────────────────────────────────────────────────────────┤
│ ⚠ 深拷贝可能很慢,大对象需谨慎 │
│ ⚠ 循环引用需要特殊处理 │
│ ⚠ 克隆后需重置运行时状态 │
│ ⚠ 浅拷贝共享可变引用,修改需注意 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 与其他模式关系 │
├─────────────────────────────────────────────────────────────┤
│ + 工厂模式:原型工厂,通过名称获取克隆 │
│ + 建造者模式:建造者创建原型,原型快速复制 │
│ + 备忘录模式:原型可用于保存状态快照 │
│ + 组合模式:组合结构的深拷贝 │
└─────────────────────────────────────────────────────────────┘
"""5.9 小结
原型模式通过复制现有对象来创建新对象,是一种高效的对象创建方式。本章从形式化定义、历史渊源、实现机制、高级技术、企业级应用等多个维度进行了深入分析。
核心要点:
形式化定义:原型模式可形式化为 $\text{Prototype}: \mathcal{O} \xrightarrow{\text{clone}} \mathcal{O}'$,满足类型一致性、对象独立性和状态等价性约束。
深浅拷贝语义:浅拷贝共享可变引用,深拷贝递归复制所有嵌套对象,需根据场景选择。
Python实现:
copy模块提供标准支持,可通过__copy__和__deepcopy__自定义行为。高级技术:循环引用处理、不可变对象优化、带验证的克隆、选择性深拷贝。
企业级应用:连接池原型、游戏实体系统、消息模板系统等展示了模式的实际价值。
最佳实践:明确拷贝语义、重置运行时状态、处理循环引用、提供克隆验证。
原型模式特别适用于创建成本较高或需要创建大量相似对象的场景,可以显著提高系统性能,同时保持代码的灵活性和可维护性。