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

- 抽象原型(Prototype):声明 clone() 方法,以便派生类实现克隆自身的能力。
- 具体原型(Concrete Prototype):实现抽象原型中的 clone() 方法,需要考虑是浅拷贝还是深拷贝。
- 客户端(Client):使用 clone() 方法创建新对象。
应用场景
- 创建成本高且需要重复创建对象:当对象的创建过程较为昂贵(如涉及数据库查询、复杂计算或大量I/O操作),可以使用原型模式来避免重复创建,从而提升性能。例如,游戏角色的存档加载、图像处理中的大文件复制等。
- 需要保存对象的历史状态或备份:在需要支持撤销(Undo)或快照(Snapshot)功能的场景下,可以使用原型模式存储对象的状态,并在需要时恢复。例如,文档编辑器的撤销功能、数据库事务回滚等。
- 系统需要减少子类的数量:通过使用原型模式,系统可以避免为每种配置创建新的子类,而是通过克隆已有对象并进行修改来生成新实例,从而减少类的数量。例如,配置文件的动态加载、不同软件版本的实例化等。
优缺点
优点:
- 简化类层次结构:通过克隆创建对象,而不是通过继承创建子类,从而减少子类数量。
- 提高对象创建效率:直接克隆已有对象,而不是重新构造,能显著提升性能。
缺点:
- 违背开闭原则:每个具体原型类需要实现克隆方法,而且该克隆方法位于类的内部。当对已有的类进行改造时,需要修改源代码,违背了开闭原则。
- 实现深拷贝较为复杂:在实现深拷贝时需要编写较为复杂的代码,特别是当对象之间存在多重的嵌套引用时,为了实现深拷贝,每一层对象对应的类都必须支持深拷贝。
代码示例
浅拷贝
浅拷贝只复制对象的第一层(即顶层对象),并不会递归地复制嵌套在对象内部的可变对象(如列表、字典、集合等)。
import copy
from abc import ABC, abstractmethod# 抽象原型类
class Prototype(ABC):@abstractmethoddef clone(self):pass# 具体原型类(Car)
class Car(Prototype):def __init__(self, brand, model, color):self.brand = brandself.model = modelself.color = colordef __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)即可。
# 具体原型类(Car)
class Car(Prototype):def __init__(self, brand, model, color, features):self.brand = brandself.model = modelself.color = colorself.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']
原型管理器
原型管理器用于管理和存储原型对象,它存储系统中常用的原型对象,并为客户端提供访问和拷贝这些原型对象的接口,能够减少重复创建原型对象的工作。
下面为深拷贝代码示例增加原型管理器:
# 原型管理器
class PrototypeManager:def __init__(self):self._prototypes = {}def register(self, name, obj):"""注册原型对象"""self._prototypes[name] = objdef 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' 未注册
参考
《设计模式的艺术》
相关文章:
Python设计模式 - 原型模式
定义 原型模式是一种创建型设计模式,它可以通过复制现有对象来创建新对象,而不是直接实例化新的对象。 结构 抽象原型(Prototype):声明 clone() 方法,以便派生类实现克隆自身的能力。具体原型(…...
金和OA C6 DownLoadBgImage任意文件读取漏洞
金和OA C6 DownLoadBgImage任意文件读取漏洞 漏洞描述 金和C6数据库是一款针对企业信息化管理而设计的高级数据库管理系统,主要应用于企业资源规划(ERP)、客户关系管理(CRM)以及办公自动化(OA)…...
【stm32学习】STM32F103实操primary(FlyMCU)
github插入图片实在是太难用了,暂时懒得学就先用CSDN吧hh 一、在设备管理器下,找到单片机,并检查与FlyMCU-搜索端口 显示的是否一致 二、在搜索串口右面的栏里选中该Port,波特率选中115200 三、选择文件夹中的.hex文件࿰…...
如何将Excel的表格存为图片?
emmm,不知道题主具体的应用场景是什么,就分享几个我一般会用到的场景下奖excel表格保存为图片的技巧吧! 先来个总结: 方法 适用场景 画质 操作难度 截图(WinShiftS) 快速保存表格,方便粘贴…...
51单片机之使用Keil uVision5创建工程以及使用stc-isp进行程序烧录步骤
一、Keil uVision5创建工程步骤 1.点击项目,新建 2.新建目录 3.选择目标机器,直接搜索at89c52选择,然后点击OK 4.是否添加起吊文件,一般选择否 5.再新建的项目工程中添加文件 6.选择C文件 7.在C文件中右键,添加…...
AUTOSAR面试题集锦(1)
最基础概念 什么是AUTOSAR?AUTOSAR到底做了什么? AUTOSAR,即汽车开放系统架构,是一套专门用于汽车的开放性的框架和行业标准,旨在标准化汽车开发的流程。 AUTOSAR 通过标准化软件接口、交换格式和方法论等内容,主要实现以下几个目标: 1. 使软件和硬件彼此独立,让应…...
【Uniapp-Vue3】从uniCloud中获取数据
需要先获取数据库对象: let db uniCloud.database(); 获取数据库中数据的方法: db.collection("数据表名称").get(); 所以就可以得到下面的这个模板: let 函数名 async () > { let res await db.collection("数据表名称…...
AIOS: 一个大模型驱动的Multi-Agent操作系统设计与Code分析
AIOS: 一个大模型驱动的Multi-Agent操作系统设计与Code分析 随着人工智能技术的快速发展,传统操作系统逐渐暴露出难以适应AI时代多样化需求的局限性。特别是在支持多个智能体协同工作方面存在显著不足。为此,我们提出了一种名为AIOS(Artifici…...
Python----Python高级(网络编程:网络基础:发展历程,IP地址,MAC地址,域名,端口,子网掩码,网关,URL,DHCP,交换机)
一、网络 早期的计算机程序都是在本机上运行的,数据存储和处理都在同一台机器上完成。随着技术的发展,人 们开始有了让计算机之间相互通信的需求。例如安装在个人计算机上的计算器或记事本应用,其运行环 境仅限于个人计算机内部。这种设置虽然…...
收集的面试资料
转载自:NLP_基于酒店评论的情感分析-CSDN博客 机器学习的一般过程 如何介绍项目: 项目背景:项目输入,输出,后续应用点 项目数据:数据来源 数据处理方法:是否有脏数据,如何处理脏数据…...
pytest-xdist 进行多进程并发测试!
在软件开发过程中,测试是确保代码质量和可靠性的关键步骤。随着项目规模的扩大和复杂性的增加,测试用例的执行效率变得尤为重要。为了加速测试过程,特别是对于一些可以并行执行的测试用 例,pytest-xdist 提供了一种强大的工具&…...
LVGL4种输入设备详解(触摸、键盘、实体按键、编码器)
lvgl有触摸、键盘、实体按键、编码器四种输入设备 先来分析一下这四种输入设备有什么区别 (1)LV_INDEV_TYPE_POINTER 主要用于触摸屏 用到哪个输入设备保留哪个其他的也是,保留触摸屏输入的任务注册,其它几种种输入任务的注册&…...
全流程安装DeepSeek开源模型
目录 配置要求安装Ollama选择大模型安装大模型对话备注 配置要求 我的电脑配置为: CPU:i7 12代 GPU:3080 内存:32g 磁盘:1T以上配置运行情况: 运行ollama run deepseek-r1:7b模型无压力,CPU/…...
人工智能领域-CNN 卷积神经网络 性能调优
在自动驾驶领域,对卷积神经网络(CNN)进行性能调优至关重要,以下从数据处理、模型架构、训练过程、超参数调整和模型部署优化等多个方面为你详细介绍调优方法,并给出相应的代码示例。 1. 数据处理 数据增强࿱…...
人工智能A*算法与CNN结合- CNN 增加卷积层的数量,并对卷积核大小进行调整
以下是一个增强版的将 A* 算法与卷积神经网络(CNN)结合的代码实现,其中 CNN 增加了卷积层的数量,并对卷积核大小进行了调整。整体思路依然是先利用 A* 算法生成训练数据,再用这些数据训练 CNN 模型,最后使用…...
机器学习中常用的评价指标
一、分类任务常用指标 1. 准确率(Accuracy) 定义:正确预测样本数占总样本数的比例。优点:直观易懂,适用于类别平衡的数据。缺点:对类别不平衡数据敏感(如欺诈检测中99%的负样本)。…...
Windows安装cwgo,一直安装的是linux平台的
Windows安装cwgo,一直安装的是linux平台的 查看 go env ,发现 GOOSlinux 临时修改 GOOS ,set GOOSwindows ,再安装。 此时,安装的就是 windows 的可执行文件。安装之后再将 GOOS 修改回来即可。...
GitHub Pages + Jekyll 博客搭建指南(静态网站)
目录 🚀 静态网站及其生成工具指南🌍 什么是静态网站?📌 静态网站的优势⚖️ 静态网站 VS 动态网站 🚀 常见的静态网站生成器对比🛠️ 使用 GitHub Pages Jekyll 搭建个人博客📌 1. 创建 GitHu…...
21.[前端开发]Day21-HTML5新增内容-CSS函数-BFC-媒体查询
王者荣耀-网页缩小的问题处理 为什么会产生这个问题?怎么去解决 可以给body设置最小宽度 1 HTML5新增元素 HTML5语义化元素 HTML5其他新增元素 2 Video、Audio元素 HTML5新增元素 - video video支持的视频格式 video的兼容性写法 HTML5新增元素 - audio audio…...
C++SLT(五)——list
目录 一、list的介绍二、list的使用list的定义方式 三、list的插入和删除push_back和pop_backpush_front和pop_frontinserterase 四、list的迭代器使用五、list的元素获取六、list的大小控制七、list的操作函数sort和reversemergeremoveremove_ifuniqueassignswap 一、list的介…...
3分钟学会!用Video-subtitle-extractor轻松提取视频硬字幕,告别手动转录烦恼
3分钟学会!用Video-subtitle-extractor轻松提取视频硬字幕,告别手动转录烦恼 【免费下载链接】video-subtitle-extractor 视频硬字幕提取,生成srt文件。无需申请第三方API,本地实现文本识别。基于深度学习的视频字幕提取框架&…...
Power Automate调用Azure Foundry智能体
Power Automate调用Azure Foundry智能体一、创建Foundry智能体二、发送HTTP请求,调用Foundry智能体三、拓展一、创建Foundry智能体 先从创建开始吧 填好,然后直接审阅并创建就行了。一个资源下可以创建多个项目 转到资源 转到门户 这里有API密钥&…...
Shell脚本工程化:great.sh框架解决运维脚本可维护性难题
1. 项目概述:一个被低估的Shell脚本构建框架如果你和我一样,常年混迹在运维、DevOps或者后端开发领域,那么对Shell脚本的感情一定是复杂的。一方面,它是我们最趁手的“瑞士军刀”,从服务器初始化、日志分析到自动化部署…...
基于大语言模型的自动化信息处理系统:从RSS聚合到AI摘要的实践
1. 项目概述:一个能帮你“读”新闻的AI助手 在信息爆炸的时代,每天光是处理订阅的RSS、关注的社交媒体动态、收藏的YouTube视频和没读完的长文,就足以让人精疲力尽。我们总想保持对行业趋势的敏感,却又被海量信息淹没,…...
GPU云服务器选型指南:从核心参数到实际部署的深度解析
在当下人工智能跟高性能计算急剧速度发展状况里,GPU云服务器正沿着从专业领域迈向更为广泛应用场景的路径前行。对于构成企业的开发者、相关技术团队来讲,怎样精准无误理解这一技术方案所具备的本质,并且于实际选型期间做出合乎情理的判断&am…...
免费AI聊天机器人部署指南:整合多模型与全栈技术实践
1. 项目概述与核心价值最近在折腾一些AI应用,发现很多朋友都想自己部署一个免费的、功能强大的聊天机器人,但要么被高昂的API费用劝退,要么被复杂的部署流程搞得头大。如果你也有同样的困扰,那么今天聊的这个项目——CNSeniorious…...
芯片晶圆平面度如何测量?半导体制造中的光学形貌检测方案
晶圆作为集成电路的核心承载基片,表面形貌的精度直接关系到光刻聚焦质量、芯片电学性能及最终良率。从8英寸到12英寸的大尺寸晶圆制造中,平面度、翘曲度(Warp)、总厚度变化(TTV)及局部平面度(SF…...
C语言指针:从零掌握指针(5) 完结篇
文章目录C语言指针:从零掌握指针(5) 完结前言一、回调函数1.1 什么是回调函数?1.2 使用回调函数二、qsort函数2.1 qsort基础2.2 排序整形数据2.3 排序浮点型数据2.4 排序结构数据三,qsort函数模拟实现C语言指针&#x…...
从0到1掌握Ansible:让自动化运维不再是梦想
最近在公司推进自动化运维的时候,发现很多同事对Ansible还是一知半解,要么就是简单用用,要么就是直接放弃。其实Ansible真的没那么复杂,我用了这么多年,今天就把我的实战经验分享给大家。 说实话,刚开始接…...
荔枝派Zero V3s新手避坑指南:从源码编译到SPI Flash烧录u-boot的完整流程
荔枝派Zero V3s开发实战:从源码编译到SPI Flash烧录的避坑手册 第一次拿到荔枝派Zero V3s开发板时,那种既兴奋又忐忑的心情至今记忆犹新。作为全志V3s芯片的经典开发平台,它凭借64MB DDR2内存、内置WiFi和丰富的外设接口,成为嵌入…...
