设计模式 创建型 原型模式(Prototype Pattern)与 常见技术框架应用 解析

在这里插入图片描述

原型模式(Prototype Pattern)是一种创建型设计模式,其核心思想在于通过复制现有的对象(原型)来创建新的对象,而非通过传统的构造函数或类实例化方式。这种方式在需要快速创建大量相似对象时尤为高效,因为它避免了重复的初始化过程。

一、核心思想

原型模式的核心思想是“克隆”生成对象,即基于一个已经存在的对象(原型)来创建新的对象实例。这样做的好处是可以提高对象创建的效率,特别是在对象初始化过程复杂或资源消耗大的情况下。

二、定义与结构

定义

原型模式使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

结构

原型模式主要包含以下几个角色:

  1. Prototype(抽象原型类):声明一个克隆自己的操作,通常是一个Clone方法。这个接口或抽象类是所有具体原型类的基类。
  2. ConcretePrototype(具体原型类):实现原型接口,提供具体的Clone方法来返回对象的副本。
  3. Client(客户类):创建一个原型对象,并通过调用该对象的克隆方法来创建新的对象实例。
角色

在原型模式中,各个角色分工明确:

  • Prototype:定义了克隆方法的接口,可以是抽象类或接口。
  • ConcretePrototype:实现了Prototype接口,提供了具体的克隆实现。
  • Client:使用原型类来创建新对象的副本。

三、实现步骤及代码示例

以Java为例,展示原型模式的实现步骤和代码示例:

1、定义抽象原型类

public abstract class Prototype implements Cloneable {public abstract void show();// 克隆方法public Object clone() throws CloneNotSupportedException {return super.clone();}
}

2、实现具体原型类

public class ConcretePrototype1 extends Prototype {private String name;public ConcretePrototype1(String name) {this.name = name;}@Overridepublic void show() {System.out.println("ConcretePrototype1: " + name);}
}public class ConcretePrototype2 extends Prototype {private String description;public ConcretePrototype2(String description) {this.description = description;}@Overridepublic void show() {System.out.println("ConcretePrototype2: " + description);}
}

3、客户端代码

public class Client {public static void main(String[] args) {try {Prototype prototype1 = new ConcretePrototype1("Prototype 1");Prototype clonedPrototype1 = (Prototype) prototype1.clone();prototype1.show();clonedPrototype1.show();Prototype prototype2 = new ConcretePrototype2("Prototype 2");Prototype clonedPrototype2 = (Prototype) prototype2.clone();prototype2.show();clonedPrototype2.show();} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}

在这个示例中,ConcretePrototype1ConcretePrototype2是具体原型类,它们实现了Prototype接口中的clone方法和show方法。客户端代码通过创建原型对象并调用其clone方法来创建新的对象实例,并展示它们的信息。

四、常见技术框架应用

虽然原型模式在Java等后端语言中更为常见,但在前端技术框架中,如JavaScript(特别是ES6及以后版本),也可以通过对象字面量、Object.create()方法或类(class)来实现类似的功能。

1、使用原生 JavaScript 实现简单原型模式

// 抽象原型(这里简单模拟,以对象形式包含 clone 方法规范)
const prototypeObj = {clone: function () {let clone = Object.create(this);clone.clone = this.clone;return clone;}
};// 具体原型:商品卡片原型
const productCardPrototype = Object.create(prototypeObj);
productCardPrototype.image = 'default.jpg';
productCardPrototype.title = 'Default Product';
productCardPrototype.price = 0;// 创建具体商品卡片实例
const productCard1 = productCardPrototype.clone();
productCard1.image = 'product1.jpg';
productCard1.title = 'Awesome Product 1';
productCard1.price = 19.99;const productCard2 = productCardPrototype.clone();
productCard2.image = 'product2.jpg';
productCard2.title = 'Fantastic Product 2';
productCard2.price = 29.99;console.log(productCard1);
console.log(productCard2);

在上述代码中:

  • 首先定义 prototypeObj 作为抽象原型基础,其 clone 方法利用 Object.create 基于当前对象(this)创建新对象,并为新对象也挂载 clone 方法,确保克隆能力延续。
  • productCardPrototype 作为具体原型,继承自抽象原型,初始化一些默认属性。
  • 最后通过多次调用 clone 方法创建不同的商品卡片实例,并按需修改各自属性。

结合 ES6 类实现更规范的原型模式

// 抽象原型(以抽象类形式)
class Prototype {constructor() {}clone() {throw new Error('Abstract clone method must be implemented.');}
}// 具体原型:员工信息原型
class EmployeePrototype extends Prototype {constructor(name, age, position) {super();this.name = name;this.age = age;this.position = position;}clone() {return new EmployeePrototype(this.name, this.age, this.position);}
}// 客户端使用
const originalEmployee = new EmployeePrototype('John Doe', 30, 'Developer');
const clonedEmployee = originalEmployee.clone();
clonedEmployee.name = 'Jane Smith';console.log(originalEmployee);
console.log(clonedEmployee);

这里:

  • Prototype 抽象类定义基本结构,clone 方法抛出错误强制子类实现。
  • EmployeePrototype 具体类继承自抽象类,在 clone 方法中通过构造函数创建新的员工对象副本,实现属性复制。
  • 客户端按需求克隆员工对象并修改个别属性。

2、在 React 中的应用

在 React 组件开发中,当需要创建相似的组件实例时,原型模式可间接体现。例如,有一个自定义的 Button 组件:

import React from 'react';// 基础按钮组件(类似原型)
const BaseButton = ({ text, onClick }) => {return <button onClick={onClick}>{text}</button>;
};// 创建不同样式的按钮实例
const PrimaryButton = (props) => <BaseButton {...props} className="primary-button" />;
const SecondaryButton = (props) => <BaseButton {...props} className="secondary-button" />;const App = () => {const handleClick = () => {console.log('Button clicked');};return (<div><PrimaryButton text="Submit" onClick={handleClick} /><SecondaryButton text="Cancel" onClick={handleClick} /></div>);
};export default App;

这里 BaseButton 可看作原型,PrimaryButtonSecondaryButton 通过复用 BaseButton 的结构,传递不同的 className 属性来生成具有不同样式的按钮实例,类似基于原型的克隆思想,快速构建相似但有差异的组件。

3、在 Vue 中的应用

以 Vue 组件为例,假设有一个模态框(Modal)组件:

<template><div class="modal" v-show="isVisible"><div class="modal-content"><h3>{{ title }}</h3><p>{{ message }}</p><button @click="closeModal">Close</button></div></div>
</template><script>
export default {name: 'Modal',data() {return {isVisible: false,title: 'Default Modal',message: 'This is a default message.'};},methods: {closeModal() {this.isVisible = false;}}
};
</script><style scoped>
.modal {/* 样式定义 */
}
.modal-content {/* 样式定义 */
}
</style>

若要创建多个不同内容的模态框,可在父组件中:

<template><div><Modal ref="modal1" :title="customModal1Title" :message="customModal1Message" /><Modal ref="modal2" :title="customModal2Title" :message="customModal2Message" /><button @click="openModal1">Open Modal 1</button><button @click="openModal2">Open Modal 2</button></div>
</template><script>
import Modal from './Modal.vue';export default {components: { Modal },data() {return {customModal1Title: 'Special Modal 1',customModal1Message: 'This is a custom message for modal 1.',customModal2Title: 'Unique Modal 2',customModal2Message: 'Another custom message for modal 2.'};},methods: {openModal1() {this.$refs.modal1.isVisible = true;},openModal2() {this.$refs.modal2.isVisible = true;}}
};
</script>

这里 Modal 组件作为原型,父组件通过传入不同的 titlemessage 属性,类似克隆并定制化模态框实例,满足不同业务场景需求,减少重复代码编写。

五、应用场景

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

  1. 避免创建代价高昂的对象:当对象的创建过程非常复杂或昂贵时,可以使用原型模式来避免重复创建。
  2. 减少初始化时间:对于需要频繁创建但内容变化不大的对象,原型模式可以显著减少初始化时间。
  3. 共享技术配置:在应用程序中,如果多个对象共享相同的技术配置,可以使用原型模式来简化配置管理。
  4. 缓存池实现:在需要大量相似对象的情况下,原型模式可以用于缓存池的实现,以提高系统性能。
  5. 游戏开发中的角色复制:在游戏中,经常需要复制游戏中的角色或对象,原型模式非常适合这类需求。
  6. 数据备份和恢复:在数据备份和恢复过程中,原型模式可以用来快速创建数据的副本。
  7. 分布式系统中的对象复制:在分布式系统中,有时需要在不同的节点之间复制对象,原型模式可以帮助实现这一点。
  8. 测试用例生成:在自动化测试中,可以通过原型模式快速生成相似的测试用例,提高测试效率。
  9. 多线程环境下的对象共享:在多线程环境中,有时需要共享某些对象,原型模式可以帮助实现对象的安全共享。
  10. 数据库对象的复制:在数据库操作中,有时需要复制数据库对象,原型模式可以帮助简化这一过程。
  11. 图形用户界面(GUI)组件的复制:在GUI开发中,有时需要复制界面组件,原型模式可以实现这一点。
  12. 配置文件的解析和生成:在处理配置文件时,原型模式可以用来解析和生成配置文件。
  13. 网络请求的模拟:在网络编程中,有时需要模拟网络请求,原型模式可以帮助实现这一点。
  14. 事件处理机制:在事件处理机制中,有时需要复制事件对象,原型模式可以帮助实现这一点。
  15. 资源管理:在资源管理中,有时需要复制资源对象,原型模式可以帮助实现这一点。
  16. 版本控制系统中的文件比较:在版本控制系统中,有时需要比较文件的不同版本,原型模式可以帮助实现这一点。
  17. 文档编辑软件中的样式复制:在文档编辑软件中,有时需要复制样式,原型模式可以帮助实现这一点。
  18. 图像处理软件中的滤镜复制:在图像处理软件中,有时需要复制滤镜,原型模式可以帮助实现这一点。
  19. 音频处理软件中的音效复制:在音频处理软件中,有时需要复制音效,原型模式可以帮助实现这一点。
  20. 视频处理软件中的特效复制:在视频处理软件中,有时需要复制特效,原型模式可以帮助实现这一点。
  21. 虚拟现实(VR)环境中的对象复制:在虚拟现实环境中,有时需要复制虚拟对象,原型模式可以帮助实现这一点。
  22. 增强现实(AR)环境中的对象复制:在增强现实环境中,有时需要复制增强对象,原型模式可以帮助实现这一点。
  23. 机器学习模型的复制:在机器学习中,有时需要复制模型,原型模式可以帮助实现这一点。
  24. 深度学习网络的复制:在深度学习中,有时需要复制神经网络,原型模式可以帮助实现这一点。
  25. 自然语言处理(NLP)任务中的文本处理:在自然语言处理任务中,有时需要复制文本对象,原型模式可以帮助实现这一点。
  26. 计算机视觉任务中的图像处理:在计算机视觉任务中,有时需要复制图像对象,原型模式可以帮助实现这一点。
  27. 语音识别任务中的音频处理:在语音识别任务中,有时需要复制音频对象,原型模式可以帮助实现这一点。
  28. 推荐系统中的用户行为分析:在推荐系统中,有时需要分析用户的行为数据,原型模式可以帮助实现这一点。
  29. 电子商务平台中的商品信息复制:在电子商务平台中,有时需要复制商品信息,原型模式可以帮助实现这一点。
  30. 社交媒体平台上的内容分享:在社交媒体平台上,有时需要分享内容,原型模式可以帮助实现这一点。

六、优缺点

优点

  1. 性能提高:通过复制现有对象来创建新对象,避免了重复的初始化过程,提高了性能。
  2. 灵活性:可以动态地添加和删除原型对象,客户端可以直接使用新增的原型来实例化对象。
  3. 简化代码:避免了重复的代码编写,提高了代码的可维护性和可读性。

缺点

  1. 浅拷贝问题:如果原型对象包含引用类型的成员变量,那么这些成员变量所引用的对象将在原型对象和新对象之间共享,可能会导致意外的副作用。需要特别注意实现深拷贝。
  2. 复杂性增加:实现深拷贝可能会增加代码的复杂性。
  3. 可维护性挑战:如果类的结构中含有许多内部状态,而且这些状态随着时间不断变化,那么维护一个准确的克隆状态可能会非常困难。

综上所述,原型模式是一种高效且灵活的创建型设计模式,适用于需要快速创建大量相似对象的场景。然而,在使用时需要注意浅拷贝和深拷贝的问题,以及可能带来的复杂性和可维护性挑战。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/66052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL(二)MySQL DDL数据库定义语言

1. MySQL DDL数据库定义语言 1.1. MySQL定义语言 进入MySQL mysql -u root -p(回车后输入密码&#xff0c;即可进入mysq1)1.1.1. 数据库操作 &#xff08;1&#xff09;查看数据库 mysql>show databases;注:MySQL语句分隔符为“&#xff1b;”   mysql库很重要它里面有…

前端页面上传文件:解决 ERR_UPLOAD_FILE_CHANGED

文章目录 引言I 问题 ERR_UPLOAD_FILE_CHANGED问题重现步骤原因II 解决方法将文件转换为base64再转回file检测文件内容是否发生变更III 知识扩展发送一个包含文件和文本的multipart/form-data请求签名优化引言 文件上传应用场景:船舶设备的新增导入(基础信息:出厂编号)船舶…

学术写作中的各种流程图如何利用Kimi进行辅助构建?

目录 1.学术论文中的流程图 2.一些小实践 3.论文中严谨的实践流程 近期小编在思考使用AI工具制作流程图和思维导图&#xff0c;结果发现Kimi现在支持流程图了&#xff0c;Kimi在学术写作中的应用变得更加广泛和深入。随着AIGC技术的不断进步&#xff0c;Kimi的功能将更加强大…

竞品分析对于ASO优化的重要性

产品要想在拥有上千万款App的App Store中脱颖而出的话&#xff0c;要有绝对优势和运营方案&#xff0c;才有可能获得用户的关注。我们要分析和自身产品相似的功能&#xff0c;了解用户获取的途径等&#xff0c;从中获取对竞品有利的因素&#xff0c;明确自身产品的增加和优化方…

什么是485专用屏蔽线

文章目录 一,485屏蔽线基本概念二,485屏蔽线结构及工作原理1、结构2、工作原理三,485屏蔽线的应用一,485屏蔽线基本概念 485屏蔽线,顾名思义,是一种应用于RS-485通信系统的屏蔽线缆。RS_485是一种常用的有线通信协议,具有长距离、高速率、低成本等优点,广泛应用于工业自…

JavaScript BOMDOM

BOM window、document、location、navigator 和 screen等&#xff0c;把它们统称为BOM&#xff08;Browser Object Model&#xff0c;浏览器对象模型&#xff09; window对象 window对象位于BOM的顶层。由浏览器创建&#xff0c;也对应JavaScript本地对象Global &#xff1…

nginx高可用集群搭建

本文介绍nginx高可用集群的搭建。利用keepalived实时检查nginx进程是否存活、keepalived的虚拟ip技术&#xff0c;达到故障转移的目的。终端用户通过访问虚拟ip&#xff0c;感知不到实际发生的故障。架构图如下&#xff1a; 0、环境 Ubuntu&#xff1a;22.04.2 ltsnginx: 1.…

【开源】创建自动签到系统—QD框架

1. 介绍 QD是一个 基于 HAR 编辑器和 Tornado 服务端的 HTTP 定时任务自动执行 Web 框架。 主要通过抓包获取到HAR来制作任务模板&#xff0c;从而实现异步响应和发起HTTP请求 2. 需要环境 2.1 硬件需求 CPU&#xff1a;至少1核 内存&#xff1a;推荐 ≥ 1G 硬盘&#xff1a;推…

【数据结构Ⅰ复习题】

如有错误欢迎指正&#xff0c;题目根据教材----------严蔚敏数据结构&#xff08;c语言版 第2版&#xff09;人民邮电电子版 数据结构Ⅰ复习题 一、填空题1&#xff0e;算法应该具备的5个重要特性有___有穷性___、确定性、可行性、输入和输出。2&#xff0e;非空单链表L中*p是头…

python爬虫--小白篇【selenium自动爬取文件】

一、问题描述 在学习或工作中需要爬取文件资源时&#xff0c;由于文件数量太多&#xff0c;手动单个下载文件效率低&#xff0c;操作麻烦&#xff0c;采用selenium框架自动爬取文件数据是不二选择。如需要爬取下面网站中包含的全部pdf文件&#xff0c;并将其转为Markdown格式。…

Edge Scdn的应用场景有哪些?

酷盾安全Edge Scdn 具备强大的安全防护能力&#xff0c;通过多层防御机制&#xff0c;如防火墙、DDoS 攻击防护、入侵检测和防御、数据加密等&#xff0c;有效抵御各种网络攻击&#xff0c;包括 DDoS 攻击、CC 攻击、SQL 注入攻击、XSS 跨站脚本攻击等&#xff0c;保障网站和应…

TCPDump参数详解及示例

TCPDump参数详解及示例 TCPDump参数详解TCPDump -G的示例TCPDump -i any -s 2048 -G 600 -p udp -Z root -n -X -tt -w %Y_%m%d_%H%M_%S.pcap &的含义TCPDump是一款强大的网络数据包截获分析工具,可以将网络中传送的数据包的完全截获下来提供分析。它支持针对网络层、协议…

Vue2: table加载树形数据的踩坑记录

table中需要加载树形数据,如图: 官网给了两个例子,且每个例子中的tree-props都是这么写的: :tree-props="{children: children, hasChildren: hasChildren}" 给我一种错觉,以为数据结构中要同时指定children和hasChildren字段,然而,在非懒加载模式下,数据结…

SpringCloudAlibaba实战入门之Sentinel服务降级和服务熔断(十五)

一、Sentinel概述 1、Sentinel是什么 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 一句话概括:sentinel即Hystrix的替代品,官网: https://sentinelguard.io/zh…

问题清除指南|关于num_classes与 BCELoss、BCEWithLogitsLoss 和 CrossEntropyLoss 的关系

前言&#xff1a;关于「 num_classes 1 」引发的探究。 2024年尾声&#xff0c;学弟问到一个问题&#xff1a;在研究工作 CNNDetection 的github开源代码 networks/trainer.py 文件的 line 27 self.model resnet50(num_classes1) 中&#xff0c;变量 num_classes 的值为1&…

grouped.get_group((‘B‘, ‘A‘))选择分组

1. df.groupby([team, df.name.str[0]]) df.groupby([team, df.name.str[0]]) 这一部分代码表示对 DataFrame df 按照 两个条件 进行分组&#xff1a; 按照 team 列&#xff08;即团队&#xff09;。按照 name 列的 首字母&#xff08;df.name.str[0]&#xff09;。 df.name.s…

SQL字符串截取函数——Left()、Right()、Substring()用法详解

SQL字符串截取函数——Left&#xff08;&#xff09;、Right&#xff08;&#xff09;、Substring&#xff08;&#xff09;用法详解 1. LEFT() 函数&#xff1a;从字符串的左侧提取指定长度的子字符串。 LEFT(string, length)string&#xff1a;要操作的字符串。length&#x…

C# 服务调用RFC函数获取物料信息,并输出生成Excel文件

这个例子是C#服务调用RFC函数&#xff0c;获取物料的信息&#xff0c;并生成Excel文件 上接文章&#xff1a;C#服务 文章目录 创建函数创建结构编写源代码创建批处理文件运行结果-成功部署服务器C#代码配置文件注意&#xff01;&#xff01; 创建函数 创建结构 编写源代码 创建…

打开idea开发软件停留在加载弹出框页面进不去

问题 idea软件点击打开&#xff0c;软件卡在加载弹框进不去。 解决方法 先进入“任务管理器”停止IDEA的任务进程 2.找到IDEA软件保存的本地数据文件夹 路径都是在C盘下面&#xff1a;路径&#xff1a;C:\Users\你的用户名\AppData\Local\JetBrains 删除目录下的文件夹&…