当前位置: 首页 > 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;使得它们能够处理高度复杂的语言模式。 我…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...