当前位置: 首页 > news >正文

【设计模式】深入理解Python中的原型设计模式

深入理解Python中的原型设计模式

在软件开发中,有时需要创建对象的过程非常复杂或者代价较高,而在同一类对象的实例之间有很多重复的属性。为了避免重复构造对象,提升性能和效率,原型设计模式(Prototype Pattern)应运而生。

原型模式是一种创建型设计模式,它允许我们通过复制现有对象来创建新的对象,而不是通过实例化类创建对象。这样不仅可以简化对象的创建过程,还能显著提高性能。

在这篇文章中,我们将全面深入探讨原型模式的定义、使用场景、Python实现方法及其优缺点。

1. 什么是原型设计模式?

原型设计模式的核心思想是:通过复制现有对象来创建新的对象。原型模式在某种程度上是一种浅拷贝或深拷贝技术,通过复制一个对象的所有属性而无需重新执行构造函数。

原型模式的核心角色

  1. 原型接口(Prototype Interface):定义一个可以克隆自身的接口,通常是通过 clone() 方法来复制对象。
  2. 具体原型类(Concrete Prototype):实现 clone() 方法,允许克隆自身。
  3. 客户端(Client):通过调用原型对象的 clone() 方法来复制对象。

原型模式的UML表示

+-----------------+
|  Prototype      |
+-----------------+
|  + clone()      |
+-----------------+▲|
+-----------------+
| ConcretePrototype|
+-----------------+
|  + clone()      |
+-----------------+
  • Prototype:定义了clone()方法,用于复制对象。
  • ConcretePrototype:具体原型类实现了clone()方法,可以生成自身的拷贝。
  • Client:客户端通过原型对象进行对象复制。

2. 原型模式的应用场景

原型模式适用于以下场景:

  1. 对象的创建成本高:当对象的创建代价昂贵,且对象构造过程非常复杂时,使用原型模式可以通过复制现有对象快速生成新的实例。
  2. 需要创建多个相似的对象:如果多个对象的结构相似,使用原型模式可以通过复制来创建多个相似的实例,而无需手动创建或配置每个实例。
  3. 需要避免依赖具体类:通过原型模式,客户端无需依赖具体类来创建对象,降低了耦合度。
  4. 实例化需要动态变化:在某些场景下,对象的结构和配置会动态改变,原型模式可以帮助通过复制动态生成具有不同配置的对象。

典型的应用场景

  • 对象池(Object Pool):为了提高性能,很多系统会维护对象池,使用原型模式复制对象池中的现有对象来减少实例化开销。
  • 游戏开发:在游戏中,有许多相似的角色、怪物或道具,使用原型模式可以快速生成这些对象。
  • 配置管理:在需要不同配置但具有相似结构的系统中,可以通过原型模式快速复制并生成配置文件。

3. Python中的原型模式实现

3.1 原型接口与实现

在Python中,原型模式可以通过 copy 模块中的 copy()deepcopy() 函数实现。Python中的拷贝分为浅拷贝和深拷贝,分别对对象的引用和实际值进行拷贝。

浅拷贝与深拷贝的区别
  • 浅拷贝:创建一个新的对象,但不复制嵌套对象的内容。对原始对象中嵌套对象的修改会反映在拷贝对象中。
  • 深拷贝:递归复制所有嵌套对象,创建一个完全独立的副本。

首先,我们定义一个Prototype类,使用clone()方法来实现对象的复制。

import copy
from abc import ABC, abstractmethod# 抽象原型类
class Prototype(ABC):@abstractmethoddef clone(self):pass

3.2 具体原型类

接下来,我们定义具体的原型类,继承Prototype类并实现clone()方法。我们使用 copy 模块来实现浅拷贝和深拷贝。

# 具体原型类
class ConcretePrototype1(Prototype):def __init__(self, value, nested_object):self.value = valueself.nested_object = nested_objectdef clone(self, deep=False):if deep:return copy.deepcopy(self)else:return copy.copy(self)def __str__(self):return f"ConcretePrototype1(value={self.value}, nested_object={self.nested_object})"# 嵌套对象
class NestedObject:def __init__(self, attribute):self.attribute = attributedef __str__(self):return f"NestedObject(attribute={self.attribute})"

3.3 客户端代码

在客户端代码中,我们创建一个ConcretePrototype1对象,并通过浅拷贝和深拷贝的方式生成副本。

# 创建原型对象
nested_obj = NestedObject("Initial Attribute")
prototype = ConcretePrototype1(10, nested_obj)# 浅拷贝
shallow_copy = prototype.clone(deep=False)
# 深拷贝
deep_copy = prototype.clone(deep=True)# 输出原型和副本的状态
print("Original Prototype:", prototype)
print("Shallow Copy:", shallow_copy)
print("Deep Copy:", deep_copy)# 修改嵌套对象的属性
nested_obj.attribute = "Modified Attribute"print("\nAfter modifying the nested object:")
print("Original Prototype:", prototype)
print("Shallow Copy:", shallow_copy)
print("Deep Copy:", deep_copy)

运行结果:

Original Prototype: ConcretePrototype1(value=10, nested_object=NestedObject(attribute=Initial Attribute))
Shallow Copy: ConcretePrototype1(value=10, nested_object=NestedObject(attribute=Initial Attribute))
Deep Copy: ConcretePrototype1(value=10, nested_object=NestedObject(attribute=Initial Attribute))After modifying the nested object:
Original Prototype: ConcretePrototype1(value=10, nested_object=NestedObject(attribute=Modified Attribute))
Shallow Copy: ConcretePrototype1(value=10, nested_object=NestedObject(attribute=Modified Attribute))
Deep Copy: ConcretePrototype1(value=10, nested_object=NestedObject(attribute=Initial Attribute))

如上所示,在修改了嵌套对象后,浅拷贝的副本中的嵌套对象也发生了变化,而深拷贝的副本保持不变。这是因为深拷贝递归复制了所有嵌套对象,确保副本是一个完全独立的对象。

4. 原型模式的优缺点

优点

  1. 提高性能:原型模式通过复制现有对象,避免了复杂对象的重新构造,特别适合那些构造过程代价高的对象。
  2. 动态对象创建:原型模式可以动态生成对象,而不依赖于具体类,实现更灵活的对象创建机制。
  3. 减少重复代码:通过克隆现有对象,可以避免重复编写对象创建代码,简化代码逻辑。
  4. 实现对象池:原型模式是实现对象池的有效手段,在池中维护一些已有对象,随时可以复制出来使用。

缺点

  1. 对象拷贝的复杂性:对于包含复杂结构或深层嵌套的对象,特别是有引用循环的对象,拷贝的实现可能会变得复杂,可能需要额外的处理来防止深拷贝出现性能问题。
  2. 潜在的对象状态问题:在一些情况下,复制对象可能会导致共享状态问题,特别是在浅拷贝时,多个对象可能会共享相同的引用,修改其中一个会影响其他对象。

5. 原型模式的改进

在Python中,由于语言的动态特性,我们可以通过定制__copy__()__deepcopy__()方法,优化对象的拷贝行为。对于复杂对象结构,可以选择性地实现浅拷贝和深拷贝。

自定义 __copy__()__deepcopy__()

class CustomPrototype:def __init__(self, name, data):self.name = nameself.data = datadef __copy__(self):print("Performing shallow copy")return CustomPrototype(self.name, self.data)def __deepcopy__(self, memo):print("Performing deep copy")new_data = copy.deepcopy(self.data, memo)return CustomPrototype(self.name, new_data)# 测试自定义拷贝行为
prototype = CustomPrototype("Original", {"key": "value"})
shallow = copy.copy(prototype)
deep = copy.deepcopy(prototype)

在自定义 __copy__()__deepcopy__() 方法时,我们可以精细控制哪些部分需要拷贝,哪些部分保持引用。这种方式可以在提高性能的同时避免冗余操作。

6. 结论

原型模式是一种灵活且高效的设计模式,通过复制现有对象来创建新的对象,从而避免了复杂的对象构造过程。在Python中,利用其内置的 copy 模块,我们可以轻松实现浅拷贝和深拷贝的功能。

原型模式尤其适合需要创建大量相似对象的场景,如对象池、游戏开发和配置管理。虽然它可以提高性能和减少重复代码,但在使用时需要特别注意对象拷贝的深度问题,以避免共享状态引发的潜在问题。

通过本文的介绍,希望你能够对原型模式的定义、应用场景和Python中的实现有一个全面的理解,并能够在实际项目中灵活应用这一模式。

相关文章:

【设计模式】深入理解Python中的原型设计模式

深入理解Python中的原型设计模式 在软件开发中,有时需要创建对象的过程非常复杂或者代价较高,而在同一类对象的实例之间有很多重复的属性。为了避免重复构造对象,提升性能和效率,原型设计模式(Prototype Pattern&…...

Django CORS配置方案

参考 https://pypi.org/project/django-cors-headers/ 在setting.py中设置 INSTALLED_APPS [......corsheaders, #添加此行 ]MIDDLEWARE[......corsheaders.middleware.CorsMiddleware, #添加此行django.middleware.common.CommonMiddleware,#django.middleware.csrf.CsrfVi…...

2024年开放式耳机哪个牌子好?推荐最好的顶级开放式耳机品牌

在当下,开放式耳机逐渐成为众多消费者的新宠。与传统入耳式耳机相比,开放式耳机展现出诸多独特之处。它可以呈现出更清晰的音质效果,让用户有更美妙的听觉体验。在佩戴感上,开放式耳机更为舒适,不会给耳朵带来压迫感。…...

零基础读懂Stable Diffusion!

前言 一文搞懂Stable Diffusion是什么,怎么训练和使用,语义信息影响生成图片的过程。>>[][加入极市CV技术交流群,走在计算机视觉的最前沿] 前几个月AIGC可谓是大热了一把,各种高质量的生成图片层出不穷,而其中…...

Hash Join 和 Index Join工作原理和性能差异

在数据库查询中,Hash Join 和 Index Join 是两种常见的表连接策略。了解它们的工作原理和性能差异有助于设计高效的数据库查询。我们可以使用 Java 模拟这两种不同的连接方式,并进行性能对比。 1. Hash Join 和 Index Join 的概念: Hash Joi…...

Apifox简介及使用

Apifox 是一款集 API文档管理、接口调试、接口自动化测试 和 Mock 功能于一体的全功能工具,旨在为开发者和测试人员提供一个高效的一站式解决方案。它融合了 Postman、Swagger、JMeter 等工具的优势,能够极大地提升团队协作和 API 开发的效率。 在实际开…...

十、IPD 实施细节(产品设计与开发管理)

产品设计与开发管理 产品设计与开发管理是IPD(集成产品开发)实施过程中的核心环节。它确保从概念设计到最终产品的实现能够按照预定的质量、成本、进度目标顺利完成,并与市场需求、技术发展及企业战略保持一致。IPD强调产品设计与开发管理过程中跨职能团队的协作、流程的系…...

MySQL-13.DQL-聚合函数

一.DQL-分组查询 二.聚合函数 -- DQL:分组查询 -- 聚合函数 -- 1.统计该企业员工数量 count select count(id) from tb_emp; select count(job) from tb_emp;select count(A) from tb_emp; select count(*) from tb_emp;-- 2.统计该企业最早入职的员工 min select min(entr…...

为什么跟别人学习如何证明定理要远比使用定理更有意义

目录 背景 为什么跟别人学习 什么是高人,如何判断 高人定义 如何判断一个人的能力? 如何考量一个人的成就? 只知道使用定理的局限性 1. 缺乏灵活性和适应性 2. 无法创新或拓展新方法 3. 容易误用或误解定理 4. 难以推理和分析复杂问…...

Qt在Win,Mac和Linux的开机自启设置

Windows Windows 使用注册表来管理开机自启的应用程序。 void runWithSystem(const QString& name, const QString& path, bool autoRun) {QSetting reg("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSetting::NativeForma…...

spring boot热部署

使用热部署解决了每次都需要重新启动的问题&#xff0c;但不过热部署的在对于改动比较小时速度可能快一些&#xff0c;改动大的话尽量停止 1.使用热部署之前需要在pom.xml文件中导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifa…...

网关与蓝牙网关有什么不同之处?

尽管蓝牙网关也属于网关的一种&#xff0c;但在实际应用和功能特性上&#xff0c;它们之间存在着显著的差异。接下来&#xff0c;我们将深入探讨蓝牙网关的独特之处&#xff0c;并与传统网关进行对比分析。 一、网关与蓝牙网关的共同之处 一对多配对能力&#xff1a;无论是网关…...

JAVA计算双十一多产品实付款优惠券的省钱方案

为了计算双十一期间多产品使用优惠券后的实付款省钱方案&#xff0c;我们需要一个更复杂的逻辑来处理优惠券的应用和叠加规则。以下是一个简化的Java示例&#xff0c;用于展示如何计算多种优惠券应用于多个产品后的实付款金额&#xff0c;并找出最省钱的方案。 首先&#xff0…...

零售行业的数字化营销转型之路

一方面&#xff0c;市场竞争激烈&#xff0c;电商平台、新兴品牌和跨界对手带来巨大压力。另一方面&#xff0c;消费者需求变化迅速&#xff0c;更加追求个性化、多元化和便捷化的购物体验&#xff0c;同时传统零售企业还面临着高成本压力&#xff0c;如租金、人力和库存等。 然…...

js的for in 和 for of的详解

for...in 和 for...of 是 JavaScript 中的两种循环结构&#xff0c;它们用于不同的场景&#xff0c;适用于不同的数据类型。下面将详细介绍它们的用法、区别以及适用场景。 1. for...in 循环 for...in 用于遍历对象的可枚举属性&#xff08;包括继承的属性&#xff09;。 语…...

前端工具函数库

流行的前端工具函数库 lodashlodash-es&#xff1a;用lodash-es代替lodashes-toolkit&#xff1a;https://www.npmjs.com/package/es-toolkitradash&#xff1a;https://github.com/sodiray/radash 补充信息&#xff1a; antd-mobile 已不再依赖 lodash&#xff0c; 淘汰 lo…...

Java程序设计:Spring boot(4)——Freemarker Thymeleaf视图技术集成

1 Freemarker 视图集成 SpringBoot 内部⽀持 Freemarker 视图技术的集成&#xff0c;并提供了⾃动化配置类 FreeMarkerAuto Configuration&#xff0c;借助⾃动化配置可以很⽅便的集成 Freemarker基础到 SpringBoot 环境中。这⾥借助⼊⻔项⽬引⼊ Freemarker 环境配置。 Start…...

JavaScript 第19章:Web Storage

在JavaScript中&#xff0c;Web存储&#xff08;Web Storage&#xff09;提供了一种在用户浏览器中持久化数据的方式。这里我们会探讨localStorage、sessionStorage以及IndexedDB&#xff0c;并提供一些简单的示例代码来展示它们的用法。 localStorage localStorage允许你在用…...

[山河2024] week2

官方WP出得很快。对照官的写下私的。大概出入不大&#xff0c;毕竟第2周。后边的才难。 Crypto E&R RSA因子分解题&#xff0c;把q的2进制反转后与p异或。关于异或的题很多&#xff0c;这个还真是头一回见&#xff0c;不过爆破方法还是一样的。 r_q int(bin(q)[2:][::…...

无限可能LangChain——开启大模型世界

什么是大语言模型&#xff1f; 大语言模型是一种人工智能模型&#xff0c;通常使用深度学习技术&#xff08;如神经网络&#xff09;来理解和生成人类语言。这些模型拥有非常多的参数&#xff0c;可以达到数十亿甚至更多&#xff0c;使得它们能够处理高度复杂的语言模式。 我…...

FastAPI子应用挂载:别再让root_path坑你一夜舶

Julia&#xff08;julialang.org&#xff09;由Stefan Karpinski、Jeff Bezanson等在2009年创建&#xff0c;目标是融合Python的易用性、C的高性能、R的统计能力、Matlab的科学计算生态。 其核心设计哲学是&#xff1a; 高性能&#xff1a;编译型语言&#xff08;JIT&#xff0…...

Leather Dress Collection开源镜像:236MB轻量级LoRA集合支持消费级GPU本地部署

Leather Dress Collection开源镜像&#xff1a;236MB轻量级LoRA集合支持消费级GPU本地部署 1. 项目介绍 Leather Dress Collection是一个专为时尚设计领域打造的轻量级AI工具包&#xff0c;基于Stable Diffusion 1.5框架开发。这个开源项目包含了12个精心调校的LoRA模型&…...

2025 图形(蓝桥杯十六届C组程序题 C 题)

样例输入&#xff1a;4 5样例输出&#xff1a;20252025202520252025代码如下&#xff1a;#include <stdio.h> #include <string.h>void draw2025(int i,int w) {const char base[] "2025";int baselen strlen(base);for(int j 0;j < w;j){printf(&…...

Spring AI Alibaba vs. AgentScope:两个阿里AI框架,如何选择?

Spring AI Alibaba vs. AgentScope&#xff1a;两个阿里AI框架&#xff0c;如何选择&#xff1f;发布日期&#xff1a;2026年4月9日前言 最近技术圈中&#xff0c;阿里巴巴开源的 Spring AI Alibaba 和 AgentScope 引发广泛讨论。两者同为阿里出品&#xff0c;但设计哲学和应用…...

M2LOrder情感分析多场景:政务热线投诉文本情绪聚类与热点发现

M2LOrder情感分析多场景&#xff1a;政务热线投诉文本情绪聚类与热点发现 1. 项目概述与核心价值 M2LOrder是一个基于.opt模型文件的情绪识别与情感分析服务&#xff0c;提供HTTP API和WebUI两种访问方式。这个系统特别适合处理政务热线中的大量投诉文本&#xff0c;能够自动…...

技术判断力之AI三问映

认识Pass层级结构 Pass范围从上到下一共分为5个层级&#xff1a; 模块层级&#xff1a;单个.ll或.bc文件 调用图层级&#xff1a;函数调用的关系。 函数层级&#xff1a;单个函数。 基本块层级&#xff1a;单个代码块。例如C语言中{}括起来的最小代码。 指令层级&#xff1a;单…...

在 ADT 里把 Released API 和 Deprecated Object 找明白,才算真正摸到 ABAP Cloud 开发的门道

很多人刚从经典的 On-Premise 开发切到 ABAP Cloud,最不适应的地方,不是 RAP,也不是 CDS view entity,而是眼前明明有一个类、一个接口、一个 CDS 实体,你却不能因为它存在就直接用。你得先确认它是不是 released,属于哪个 release contract,有没有被放进可用的 API Cat…...

Win11Debloat终极指南:一键清理Windows 11垃圾,让你的电脑飞起来!

Win11Debloat终极指南&#xff1a;一键清理Windows 11垃圾&#xff0c;让你的电脑飞起来&#xff01; 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various …...

FireRedASR-AED-L语音识别模型WebUI部署教程:Python环境快速配置指南

FireRedASR-AED-L语音识别模型WebUI部署教程&#xff1a;Python环境快速配置指南 想试试最新的语音识别模型&#xff0c;但被复杂的Python环境配置和依赖包冲突劝退&#xff1f;这感觉我太懂了。每次看到新模型发布&#xff0c;兴致勃勃地准备上手&#xff0c;结果第一步环境搭…...

Lenovo Legion Toolkit革新:全场景精准调控拯救者笔记本性能

Lenovo Legion Toolkit革新&#xff1a;全场景精准调控拯救者笔记本性能 【免费下载链接】LenovoLegionToolkit Lightweight Lenovo Vantage and Hotkeys replacement for Lenovo Legion laptops. 项目地址: https://gitcode.com/gh_mirrors/le/LenovoLegionToolkit Len…...