Python设计模式 - 原型模式

定义

原型模式是一种创建型设计模式,它可以通过复制现有对象来创建新对象,而不是直接实例化新的对象。

结构

  • 抽象原型(Prototype):声明 clone() 方法,以便派生类实现克隆自身的能力。
  • 具体原型(Concrete Prototype):实现抽象原型中的 clone() 方法,需要考虑是浅拷贝还是深拷贝
  • 客户端(Client):使用 clone() 方法创建新对象。

应用场景

  1. 创建成本高且需要重复创建对象:当对象的创建过程较为昂贵(如涉及数据库查询、复杂计算或大量I/O操作),可以使用原型模式来避免重复创建,从而提升性能。例如,游戏角色的存档加载、图像处理中的大文件复制等。
  2. 需要保存对象的历史状态或备份:在需要支持撤销(Undo)或快照(Snapshot)功能的场景下,可以使用原型模式存储对象的状态,并在需要时恢复。例如,文档编辑器的撤销功能、数据库事务回滚等。
  3. 系统需要减少子类的数量:通过使用原型模式,系统可以避免为每种配置创建新的子类,而是通过克隆已有对象并进行修改来生成新实例,从而减少类的数量。例如,配置文件的动态加载、不同软件版本的实例化等。

优缺点

优点:

  1. 简化类层次结构:通过克隆创建对象,而不是通过继承创建子类,从而减少子类数量。
  2. 提高对象创建效率:直接克隆已有对象,而不是重新构造,能显著提升性能。

缺点:

  1. 违背开闭原则:每个具体原型类需要实现克隆方法,而且该克隆方法位于类的内部。当对已有的类进行改造时,需要修改源代码,违背了开闭原则。
  2. 实现深拷贝较为复杂:在实现深拷贝时需要编写较为复杂的代码,特别是当对象之间存在多重的嵌套引用时,为了实现深拷贝,每一层对象对应的类都必须支持深拷贝。

代码示例

浅拷贝

浅拷贝只复制对象的第一层(即顶层对象),并不会递归地复制嵌套在对象内部的可变对象(如列表、字典、集合等)。

python 复制代码
import copy
from abc import ABC, abstractmethod


# 抽象原型类
class Prototype(ABC):
    @abstractmethod
    def clone(self):
        pass


# 具体原型类(Car)
class Car(Prototype):
    def __init__(self, brand, model, color):
        self.brand = brand
        self.model = model
        self.color = color

    def __str__(self):
        return f"{self.color} {self.brand} {self.model}"

    def clone(self, **attrs):
        """克隆对象,并允许修改部分属性"""
        # 创建浅拷贝
        cloned_obj = copy.copy(self)
        # 更新克隆对象的属性
        cloned_obj.__dict__.update(attrs)
        return cloned_obj


# 创建原型对象
car1 = Car("Tesla", "Model S", "Red")

# 克隆对象,并修改颜色
car2 = car1.clone(color="Blue")

print(car1)  # 输出: Red Tesla Model S
print(car2)  # 输出: Blue Tesla Model S

深拷贝

深拷贝会递归地复制对象及其所有嵌套的可变对象,创建一个完全独立的新对象。

深拷贝的代码只需要在浅拷贝代码的基础上把copy.copy(self)改成copy.deepcopy(self)即可。

python 复制代码
# 具体原型类(Car)
class Car(Prototype):
    def __init__(self, brand, model, color, features):
        self.brand = brand
        self.model = model
        self.color = color
        self.features = features  # 可变对象(如列表)

    def __str__(self):
        return f"{self.color} {self.brand} {self.model}"

    def clone(self, **attrs):
        """深拷贝对象,并允许修改部分属性"""
        # 创建深拷贝
        cloned_obj = copy.deepcopy(self)
        # 更新克隆对象的属性
        cloned_obj.__dict__.update(attrs)
        return cloned_obj


# 创建原型对象
car1 = Car("Tesla", "Model S", "Red", ["Autopilot", "Glass Roof"])

# 克隆对象,并修改颜色
car2 = car1.clone(color="Blue")

# 修改 car2 的 features
car2.features.append("Self-driving")

# 查看 car1 和 car2 的内容
print("car1:", car1)  # 输出: Red Tesla Model S
print("car2:", car2)  # 输出: Blue Tesla Model S
print("car1.features:", car1.features)  # 输出: ['Autopilot', 'Glass Roof']
print("car2.features:", car2.features)  # 输出: ['Autopilot', 'Glass Roof', 'Self-driving']

原型管理器

原型管理器用于管理和存储原型对象,它存储系统中常用的原型对象,并为客户端提供访问和拷贝这些原型对象的接口,能够减少重复创建原型对象的工作。

下面为深拷贝代码示例增加原型管理器:

python 复制代码
# 原型管理器
class PrototypeManager:
    def __init__(self):
        self._prototypes = {}

    def register(self, name, obj):
        """注册原型对象"""
        self._prototypes[name] = obj

    def unregister(self, name):
        """移除原型对象"""
        if name in self._prototypes:
            del self._prototypes[name]

    def clone(self, name, **attrs):
        """克隆对象,并可修改部分属性"""
        if name not in self._prototypes:
            raise ValueError(f"原型 '{name}' 未注册")
        return self._prototypes[name].clone(**attrs)


# 创建原型管理器
prototype_manager = PrototypeManager()

# 创建一个Car实例,并注册到原型管理器
car1 = Car("Tesla", "Model S", "Red", ["Autopilot", "Glass Roof"])
prototype_manager.register("electric_car", car1)

# 克隆对象,并修改颜色
car2 = prototype_manager.clone("electric_car", color="Blue")

print(car1)  # 输出: Red Tesla Model S
print(car2)  # 输出: Blue Tesla Model S

# 取消注册某个原型
prototype_manager.unregister("electric_car")

# 再次尝试克隆(会抛出异常)
try:
    car3 = prototype_manager.clone("electric_car")
except ValueError as e:
    print(e)  # 输出: 原型 'electric_car' 未注册

参考

《设计模式的艺术》

相关推荐
十五年专注C++开发12 分钟前
设计模式之单例模式(二): 心得体会
开发语言·c++·单例模式·设计模式
nenchoumi311913 分钟前
AirSim/Cosys-AirSim 游戏开发(一)XBox 手柄 Windows + python 连接与读取
windows·python·xbox
GoodStudyAndDayDayUp14 分钟前
初入 python Django 框架总结
数据库·python·django
hstar952714 分钟前
三十五、面向对象底层逻辑-Spring MVC中AbstractXlsxStreamingView的设计
java·后端·spring·设计模式·架构·mvc
星辰大海的精灵22 分钟前
基于Dify+MCP实现通过微信发送天气信息给好友
人工智能·后端·python
精灵vector27 分钟前
Agent短期记忆的几种持久化存储方式
人工智能·python
pengyu40 分钟前
【Java设计原则与模式之系统化精讲:壹】 | 编程世界的道与术(实战指导篇)
java·后端·设计模式
北京_宏哥42 分钟前
🔥Python零基础从入门到精通详细教程4-数据类型的转换- 上篇
前端·python·面试
乾巫宇宙国监察特使1 小时前
Python的设计模式
python·测试
Hockor1 小时前
写给前端的 Python 教程四(列表/元组)
前端·后端·python