Skip to content

第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 → Clone

Self语言证明,无需类的概念也能实现面向对象编程,原型本身即是对象,新对象通过克隆现有对象创建。

3. GoF分类(1994)

Gamma等人在《Design Patterns》中将原型模式归类为创建型模式,强调其"通过复制创建对象"的核心思想,并定义了Prototype接口与ConcretePrototype的标准结构。

4. 现代演进

现代编程语言对原型模式的支持呈现两种路径:

  • 内置支持型:Python的copy模块、Java的Cloneable接口、C#的ICloneable
  • 语言级原型:JavaScript的原型链继承机制

5.1.3 模式动机

原型模式解决以下核心问题:

问题1:对象创建成本高昂

python
class ComplexSimulation:
    def __init__(self):
        self.data = self._expensive_computation()
    
    def _expensive_computation(self) -> dict:
        import time
        time.sleep(5)
        return {"result": "computed"}

每次创建新实例需执行耗时计算,而克隆可跳过初始化过程。

问题2:对象结构复杂

python
class ComplexObject:
    def __init__(self):
        self.nested = NestedObject()
        self.nested.deep = DeepObject()
        self.nested.deep.values = [1, 2, 3]

手动复制复杂嵌套结构容易出错,原型模式提供标准化复制机制。

问题3:运行时动态类型

python
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]  │
           └──────────┘                  └──────────┘                  └──────────┘


                                                              独立副本 ───┘

浅拷贝实现原理

python
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()

深拷贝实现原理

python
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()

拷贝性能对比

python
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的标准实现

python
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的现代实现

python
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__

python
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 原型注册表模式

python
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 循环引用处理

python
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 不可变对象克隆

python
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 带验证的克隆

python
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 数据库连接池原型

python
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 游戏实体原型系统

python
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 消息模板原型

python
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 性能考量与优化策略

python
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 组合使用模式

python
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 常见反模式

python
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 最佳实践清单

python
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 快速参考卡

python
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 小结

原型模式通过复制现有对象来创建新对象,是一种高效的对象创建方式。本章从形式化定义、历史渊源、实现机制、高级技术、企业级应用等多个维度进行了深入分析。

核心要点

  1. 形式化定义:原型模式可形式化为 $\text{Prototype}: \mathcal{O} \xrightarrow{\text{clone}} \mathcal{O}'$,满足类型一致性、对象独立性和状态等价性约束。

  2. 深浅拷贝语义:浅拷贝共享可变引用,深拷贝递归复制所有嵌套对象,需根据场景选择。

  3. Python实现copy模块提供标准支持,可通过__copy____deepcopy__自定义行为。

  4. 高级技术:循环引用处理、不可变对象优化、带验证的克隆、选择性深拷贝。

  5. 企业级应用:连接池原型、游戏实体系统、消息模板系统等展示了模式的实际价值。

  6. 最佳实践:明确拷贝语义、重置运行时状态、处理循环引用、提供克隆验证。

原型模式特别适用于创建成本较高或需要创建大量相似对象的场景,可以显著提高系统性能,同时保持代码的灵活性和可维护性。

Python技术丛书 - 江苏省宿城中等专业学校