设计模式- 原型模式(Prototype Pattern)结构|原理|优缺点|场景|示例

                            ​​​​​​​        设计模式(分类)        设计模式(六大原则)   

    创建型(5种)        工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式

    结构型(7种)        适配器模式        装饰器模式        代理模式        ​​​​​​外观模式      桥接模式        组合模式       享元模式

    行为型(11种)      策略模式        模板方法模式        观察者模式        迭代器模式        责任链模式        命令模式

                                   备忘录模式          状态模式          访问者模式        中介者模式    


原型模式(Prototype Pattern)是一种创建型设计模式,其主要目的是通过复制现有的对象(即原型)来创建新对象,而不是每次都通过new操作符来创建对象。这种模式适用于创建新对象的成本较大(如初始化耗时、占用资源较多)或者创建过程较复杂的场景,通过克隆原型对象可以快速、便捷地生成相似或相同状态的新对象。

模式结构

原型模式通常包含以下角色:

  1. 原型(Prototype):定义一个克隆自身的接口,通常包含一个clone()方法。
  2. 具体原型(Concrete Prototype):实现原型接口,提供克隆自身的具体实现。具体原型类需要能够复制自身的状态,并可能包含必要的辅助方法来支持复制过程。

工作原理

  • 客户端:通过调用具体原型对象的clone()方法来创建新对象,无需关心对象的内部构造细节。
  • 具体原型:实现clone()方法,负责复制自身的状态,并可能需要处理深层次对象的递归复制。新创建的对象与原对象状态相同,但具有独立的标识(即不同的内存地址)。

优缺点

优点
  • 简化对象创建过程:对于复杂的对象,使用原型模式可以简化对象的创建过程,避免重复初始化或执行耗时的操作。
  • 提高性能:通过复制现有对象创建新对象,特别是在对象初始化成本较高的情况下,可以显著提高性能。
  • 支持动态增加或修改产品类:如果产品类需要动态添加或修改,使用原型模式可以避免对客户端代码产生影响。
缺点
  • 对象必须支持克隆:不是所有的对象都能很容易地实现克隆,尤其是包含复杂状态或引用其他对象时,克隆实现可能变得复杂。
  • 深拷贝与浅拷贝问题:在复制包含其他对象引用的状态时,需要考虑是否需要深度复制这些引用对象,否则可能导致数据不一致或意外共享状态。

适用场景

  • 对象创建成本较高:当创建新对象需要消耗大量资源、执行复杂操作或初始化时间较长时,使用原型模式可以有效提高效率。
  • 需要动态创建相似或相同状态的对象:如游戏中的角色复制、文档模板应用、数据恢复场景等,通过克隆原型对象快速生成新对象。
  • 需要避免对象之间的相互依赖:通过复制已有对象来创建新对象,可以减少对象间的依赖关系,降低系统的耦合度。

代码示例(以Java为例)

在Java中实现原型模式,可以利用Java内建的Cloneable接口和Object类提供的clone()方法。下面是一个简单的Java代码示例:

// 原型接口(由于Java中没有显式的原型接口,此处省略)// 具体原型类实现Cloneable接口以支持克隆
public class ConcretePrototype implements Cloneable {private String attr1;private String attr2;public ConcretePrototype(String attr1, String attr2) {this.attr1 = attr1;this.attr2 = attr2;}// 提供公共的clone方法@Overridepublic ConcretePrototype clone() throws CloneNotSupportedException {return (ConcretePrototype) super.clone();}// 其他方法、属性...public String getAttr1() {return attr1;}public String getAttr2() {return attr2;}
}// 客户端代码
public class Client {public static void main(String[] args) {try {ConcretePrototype prototype = new ConcretePrototype("value1", "value2");ConcretePrototype clonedObject = prototype.clone();System.out.println(clonedObject.getAttr1());  // 输出:value1System.out.println(clonedObject.getAttr2());  // 输出:value2} catch (CloneNotSupportedException e) {// 不应该发生,因为ConcretePrototype实现了Cloneable接口e.printStackTrace();}}
}

在这个Java示例中:

  • ConcretePrototype类实现了Cloneable接口,表明它可以被克隆。
  • 重写了Object类的clone()方法,并将其声明为public,以便客户端可以直接调用。注意,虽然Cloneable接口没有实际的方法定义,但它是一个标记接口,用于指示对象支持克隆操作。
  • clone()方法中,调用super.clone()来执行实际的克隆过程。这会创建一个浅拷贝,即原始对象和克隆对象共享不可变的基本类型和对象引用。如果类中包含复杂对象或可变集合,可能需要在clone()方法中进行深度拷贝,以确保新对象的独立性。
  • 客户端代码通过调用prototype.clone()来创建新对象,捕获可能出现的CloneNotSupportedException异常(尽管在正确实现Cloneable的情况下,此异常通常不会抛出)。

请注意,Java的clone()方法默认执行的是浅拷贝,如果对象内部包含可变的复杂对象或集合,需要在clone()方法中手动进行深拷贝,以确保新对象的状态完整独立。例如,如果ConcretePrototype类中有一个可变的列表成员变量,需要在clone()方法中对其进行单独复制:

private List<String> items;// ...其他代码...@Override
public ConcretePrototype clone() throws CloneNotSupportedException {ConcretePrototype clone = (ConcretePrototype) super.clone();clone.items = new ArrayList<>(this.items);  // 深拷贝列表return clone;
}

代码示例(以Python为例)

import copy# 原型接口
class Prototype:def clone(self):raise NotImplementedError("Subclasses must implement this method")# 具体原型
class ConcretePrototype(Prototype):def __init__(self, attr1, attr2):self.attr1 = attr1self.attr2 = attr2def clone(self):return copy.deepcopy(self)# 客户端代码
def main():prototype = ConcretePrototype("value1", "value2")cloned_object = prototype.clone()print(cloned_object.attr1, cloned_object.attr2)  # 输出:value1 value2if __name__ == "__main__":main()

在这个Python示例中:

  • Prototype类作为原型接口,定义了clone()方法,要求子类必须实现。
  • ConcretePrototype类继承自Prototype,实现了具体的clone()方法。这里使用copy.deepcopy()来实现深度克隆,确保新创建的对象与原对象状态相同且具有独立的标识。
  • 客户端代码通过调用ConcretePrototype对象的clone()方法来创建新对象,无需关心对象的内部构造细节。新创建的对象与原对象状态相同,但具有独立的标识。

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

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

相关文章

python创建线程和结束线程

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 python创建线程和结束线程 在 Python 中&#xff0c;线程是一种轻量级的执行单元&#xff…

进程概念(进程第1篇)【Linux复习篇】

目录 1、冯诺依曼体系结构怎么画&#xff1f;中央处理器是什么&#xff1f;存储器是什么&#xff1f;每个部分有什么作用&#xff1f; 2、什么是操作系统&#xff1f; 3、什么叫进程&#xff1f;操作系统如何管理进程的&#xff1f; 4、怎么查看进程&#xff1f; 5、C语言…

基于MLP算法实现交通流量预测(Pytorch版)

在海量的城市数据中&#xff0c;交通流量数据无疑是揭示城市运行脉络、洞察出行规律的关键要素之一。实时且精准的交通流量预测不仅能为交通规划者提供科学决策依据&#xff0c;助力提升道路使用效率、缓解交通拥堵&#xff0c;还能为公众出行提供参考&#xff0c;实现个性化导…

指令和界面【Linux】

指令和界面 前言一、指令 vs 界面交互的需求满足需求的第一阶段——指令满足需求的第二阶段-界面时间 二、指令和界面交互区别为什么要学命令行总结 前言 Linux操作系统提供了丰富的命令行界面和图形用户界面工具&#xff0c;用户可以根据自己的需求选择适合的界面进行操作。命…

【好书推荐7】《机器学习平台架构实战》

【好书推荐7】《机器学习平台架构实战》 写在最前面《机器学习平台架构实战》编辑推荐内容简介作者简介目  录前  言本书读者内容介绍充分利用本书下载示例代码文件下载彩色图像本书约定 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&…

论文阅读:BEVBert: Multimodal Map Pre-training for Language-guided Navigation

BEVBert&#xff1a;语言引导导航的多模态地图预训练 摘要 现存的问题&#xff1a;目前大多数现有的预训练方法都采用离散的全景图来学习视觉-文本关联。这要求模型隐式关联全景图中不完整、重复的观察结果&#xff0c;这可能会损害智能体的空间理解。 本文解决方案&#xf…

TikTok账号0播放是限流了吗?想要播放破万,试试这些方法!

前言 账号0播放问题&#xff0c;想必困扰着许多的TikTok运营同学。精心制作的短视频发布在TikTok&#xff0c;不是零播放&#xff0c;就是仅自己可见。那么&#xff0c;TikTok账号0播放是不是真的意味着被限流了呢&#xff1f;本篇总结了账号0播放的原因并附上解决方案&#xf…

[Flutter3] Json转dart模型举例

记录一下 Android studio plugin -> FlutterJsonBeanFactory 处理json转dart 模型 案例 json字符串, 一个 response的data返回数据 {"code":1,"msg":"\u64cd\u4f5c\u6210\u529f","data":{"list":{"id":"8…

SwiftUI 5.0(iOS 17.0)触摸反馈“震荡波”与触发器模式趣谈

概览 要想创作出一款精彩绝伦的 App&#xff0c;绚丽的界面和灵动的动画并不是唯一吸引用户的要素。有时我们还希望让用户真切的感受到操作引发的触觉反馈&#xff0c;直击使用者的灵魂。 所幸的是新版 SwiftUI 原生提供了实现触觉震动反馈的机制。在介绍它之后我们还将进一步…

等保测评之主机测评详解(二级)

等保测评之主机测评详解&#xff08;二级&#xff09;服务器——Windows 身份鉴别: 测评项a&#xff09;&#xff1a; a&#xff09;应对登录的用户进行身份标识和鉴别&#xff0c;身份标识具有唯一性&#xff0c;身份鉴别信息具有复杂度要求并定期更换&#xff1b; 整改方…

antd中Upload上传图片宽高限制以及上传文件的格式限制

项目中有一个需求&#xff0c;要上传轮播图&#xff0c;且有尺寸要求&#xff0c;所以就需要在上传图片的时候进行尺寸限制&#xff0c;使用了Upload组件&#xff0c;需要在组件的beforeUpload方法中进行限制。 定义一个上传前的方法&#xff0c;并且添加一个图片尺寸获取的方…

【Redis】Zset 数据类型

文章目录 常用命令zaddzcard & zcountzrange & zrevrangezpopmax & bzpopmaxzpopmin & bzpopminzrank & zrevrankzscore & zremzremrangebyrank & zremrangebyscorezincrby 多个集合间的交互命令交集 & zinterstore并集 & sunionstore 内部…

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡 配置ssh远程连接docker1.端口映射2.配置ssh 在docker中使用nvidia显卡配置CUDA 注意&#xff1a;之前已经创建过容器的&#xff0c;需要打包成镜像&#xff0c;重新创建容器&#xff0c;因为要在创建…

【C++庖丁解牛】C++11---右值引用和移动语义

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1 左值引用和右值引用2 左…

第一个Spring Boot程序

目录 一、Spring Boot介绍 二、创建Spring Boot项目 1、插件安装&#xff08;专业版不需要&#xff09; 2、创建SpringBoot项目 &#xff08;1&#xff09;这里如果插件下载失败&#xff0c;解决方案&#xff1a; &#xff08;2&#xff09;项目启动失败&#xff0c;解决…

web测试基础知识

目录 web系统的基础 web概念(worldwideweb) 网络结构 发展 架构 B/S C/S P2P 工作原理 静态页面 动态页面 web客户端技术 浏览器的核心--渲染引擎 web服务器端技术 web服务器 应用服务器 集群环境 数据库 案例-URL 协议类型 主机名 端口 IP地址 分类 …

C#开发的全套成熟的LIS系统源码JavaScript+SQLserver 2012区域云LIS系统源码

C#开发的全套成熟的LIS系统源码JavaScriptSQLserver 2012区域云LIS系统源码 医院云LIS系统是一套成熟的实验室信息管理系统&#xff0c;目前已在多家三级级医院应用&#xff0c;并不断更新。云LIS系统是为病人为中心、以业务处理为基础、以提高检验科室管理水平和工作效率为目标…

贪心算法练习day.1

理论基础 贪心算法是一种常见的解决优化问题的方法&#xff0c;其基本思想就是在问题的每个决策阶段&#xff0c;都选择当前看起来最优的选择&#xff0c;即贪心地做出局部的最优决策&#xff0c;以此得到全局的最优解&#xff0c;例如在十张面额不同的钞票&#xff0c;让我们…

润申信息企业标准化管理系统 AddNewsHandler.ashx 任意用户创建漏洞复现

0x01 产品简介 润申信息科技企业标准化管理系统通过给客户提供各种灵活的标准法规信息化管理解决方案,帮助他们实现了高效的标准法规管理,完成个性化标准法规库的信息化建设。 0x02 漏洞概述 润申信息企业标准化管理系统 AddNewsHandler.ashx 接口处存在任意用户创建漏洞,…

Linux安装部署Tomcat

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Linux安装部署Tomcat //将tomcat压缩包解压到对…