Python 原型模式

Python 中的原型模式(Prototype Pattern)

原型模式是一种创建型设计模式,其核心思想是:
用一个已存在的对象(原型)作为模板,通过复制(克隆)来创建新的对象,而不是通过 new 或构造函数重新创建。

适用场景

  • 创建对象代价高昂(需要大量初始化、IO、网络请求等)
  • 对象结构复杂,但大部分属性相似,只需微调
  • 希望避免显式构造函数参数爆炸
  • 需要快速生成大量相似对象(如游戏中的怪物、UI 组件、报表模板等)

原型模式的优点

  • 隐藏创建细节,客户端只需调用 clone()
  • 性能好:复制比重新构建快得多
  • 方便扩展:只需克隆再修改

Python 中的实现方式

Python 提供了非常方便的内置支持:
copy 模块中的 copy()(浅拷贝)和 deepcopy()(深拷贝),以及 __copy____deepcopy__ 钩子。

1. 最简单的原型模式:使用 copy.deepcopy()
import copy

class Prototype:
    def __init__(self, name, age, skills):
        self.name = name
        self.age = age
        self.skills = skills  # 列表,深拷贝时会复制

    def clone(self):
        return copy.deepcopy(self)

    def __str__(self):
        return f"{self.name} ({self.age}), skills: {self.skills}"


# 使用
if __name__ == "__main__":
    original = Prototype("Alice", 28, ["Python", "Java", "SQL"])

    clone1 = original.clone()
    clone1.name = "Bob"
    clone1.age = 30
    clone1.skills.append("Go")

    clone2 = original.clone()
    clone2.name = "Charlie"

    print("Original:", original)
    print("Clone1:  ", clone1)
    print("Clone2:  ", clone2)

输出

Original: Alice (28), skills: ['Python', 'Java', 'SQL']
Clone1:   Bob (30), skills: ['Python', 'Java', 'SQL', 'Go']
Clone2:   Charlie (28), skills: ['Python', 'Java', 'SQL']
2. 更优雅的方式:自定义 __copy____deepcopy__
import copy

class Employee:
    def __init__(self, name, department, projects):
        self.name = name
        self.department = department
        self.projects = projects  # 列表

    def __copy__(self):
        # 浅拷贝:只复制对象本身,列表引用共享
        new = self.__class__.__new__(self.__class__)
        new.__dict__.update(self.__dict__)
        return new

    def __deepcopy__(self, memo=None):
        # 深拷贝:递归复制所有可变对象
        new = self.__class__.__new__(self.__class__)
        new.__dict__.update({
            'name': self.name,
            'department': self.department,
            'projects': copy.deepcopy(self.projects, memo)
        })
        return new

    def clone(self, deep=False):
        return copy.deepcopy(self) if deep else copy.copy(self)

    def __str__(self):
        return f"{self.name} in {self.department}, projects: {self.projects}"


# 测试
emp = Employee("Alice", "Engineering", ["Project A", "Project B"])

# 浅拷贝
emp_shallow = emp.clone(deep=False)
emp_shallow.name = "Bob"
emp_shallow.projects.append("Project C")

print("Original:", emp)
print("Shallow clone:", emp_shallow)  # projects 列表是共享的

# 深拷贝
emp_deep = emp.clone(deep=True)
emp_deep.name = "Charlie"
emp_deep.projects.append("Project D")

print("Original (unchanged):", emp)
print("Deep clone:", emp_deep)

输出

Original: Alice in Engineering, projects: ['Project A', 'Project B', 'Project C']
Shallow clone: Bob in Engineering, projects: ['Project A', 'Project B', 'Project C']
Original (unchanged): Alice in Engineering, projects: ['Project A', 'Project B', 'Project C']
Deep clone: Charlie in Engineering, projects: ['Project A', 'Project B', 'Project D']
3. 原型管理器(Prototype Registry)—— 注册原型并按名称克隆
import copy

class PrototypeRegistry:
    def __init__(self):
        self._prototypes = {}

    def register(self, name, prototype):
        self._prototypes[name] = prototype

    def unregister(self, name):
        del self._prototypes[name]

    def clone(self, name, **attrs):
        prototype = self._prototypes[name]
        clone = copy.deepcopy(prototype)
        clone.__dict__.update(attrs)  # 覆盖或添加属性
        return clone


# 使用
if __name__ == "__main__":
    registry = PrototypeRegistry()

    # 注册几种模板
    registry.register("basic_car", Car("Basic Car", "Sedan", "Red", 100000))
    registry.register("sports_car", Car("Sports Car", "Coupe", "Black", 300000))

    # 克隆并修改
    car1 = registry.clone("basic_car", color="Blue", price=120000)
    car2 = registry.clone("sports_car", name="Ferrari", color="Yellow", price=500000)

    print(car1)
    print(car2)

原型模式 vs 其他创建型模式对比

模式适用场景是否需要构造函数
工厂方法根据类型创建不同对象
抽象工厂创建一组相关对象
建造者复杂对象一步步构建否(链式)
原型复制已有对象(尤其是初始化代价高)否(直接 clone)

Python 中的实际推荐

  • 大多数情况下,直接用 copy.deepcopy() 就够了。
  • 需要控制浅/深拷贝行为时,自定义 __copy____deepcopy__
  • 需要管理多种模板时,使用原型注册器(Registry)。

真实项目中的例子

  • 游戏开发:克隆怪物、技能、物品
  • 报表系统:克隆报表模板,再修改标题、字段
  • 图形编辑器:复制图形对象
  • 机器学习:复制模型配置,再微调

如果你想看更复杂的例子(如游戏角色原型、图形对象克隆、结合其他模式的实现),随时告诉我!

文章已创建 3511

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部