设计模式创建型——原型模式
目录什么是原型模式原型模式的实现原型模式分类浅克隆和深克隆的区别原型模式浅克隆原型模式深克隆原型模式简单实现方式原型模式登记实现方式原型模式的特点特点优点缺点应用场景什么是原型模式原型模式Prototype Pattern是用于创建重复的对象同时又能保证性能。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式之一。用原型实例指定创建对象的种类并且通过拷贝这些原型创建新的对象允许一个对象再创建另外一个可定制的对象无需知道如何创建的细节。原型模式简化了创建对象的过程通过一个已有的实例进行复制提高了创建实例的效率具有较好的可扩展性。通过将一个原型对象传给那个要发动创建的对象这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建即 对象.clone()用于创建当前对象的克隆。当直接创建对象的代价比较大时则采用这种模式。例如一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象在下一个请求时返回它的克隆在需要的时候更新数据库以此来减少数据库调用。原型模式的实现原型模式分类浅克隆创建一个新对象新对象的属性和原来对象完全相同对于非基本类型属性仍指向原有属性所指向的对象的内存地址。深克隆创建一个新对象属性中引用的其他对象也会被克隆不再指向原有对象地址。浅克隆和深克隆的区别使用浅克隆时当原型对象被复制时只复制它本身和其中包含的值类型的成员变量而引用类型的成员变量并没有复制而使用深克隆时除了对象本身被复制外对象所包含的所有成员变量也将被复制。在java 中浅克隆是继承Cloneable接口后重写clone方法完成的克隆而深克隆需要继承序列化接口Serializable使类可以序列化然后将类写入流中再从流中取出完成克隆。下面我们用代码展示浅克隆和深克隆。原型模式浅克隆/** * author Evan Walker * version 1.0 * desc 昂焱数据: https://www.ayshuju.com * date 2023/04/10 14:17:40 */ public class Room implements Cloneable { public Room room; private String name; private int size; private String color; private String address 上海市奉贤区奉城镇南奉公路686号4幢; public Room() { } public Room(String name, int size, String color) { super(); this.name name; this.size size; this.color color; } public String getName() { return name; } public void setName(String name) { this.name name; } public int getSize() { return size; } public void setSize(int size) { this.size size; } public String getColor() { return color; } public void setColor(String color) { this.color color; } Override public String toString() { return Sheep [name name , size size , color color , address address ]; } /** * 重写clone方法或者用默认的clone方法也行只不过调用时候需要抛异常 */ Override protected Object clone() { Room room null; try { room (Room) super.clone(); } catch (Exception e) { System.out.println(e.getMessage()); } return room; } public static void main(String[] args) { System.out.println(原型模式完成对象的创建); Room room1 new Room(昂焱数据, 1, 白色); room1.room new Room(昂焱数据, 2, 黑色); Room room2 (Room) room1.clone(); Room room3 (Room) room1.clone(); System.out.println(room1.getColor().hashCode() room2.getColor().hashCode()); System.out.println(room1.getColor() room2.getColor()); System.out.println(room1.getName().hashCode() room2.getName().hashCode()); room1.room.setName(昂焱科技); System.out.println(room1.room.getName()); System.out.println(room2.room.getName()); System.out.println(room1.room.getName().hashCode() room2.room.getName().hashCode()); System.out.println(room1.room.getName() room2.room.getName()); System.out.println(room1.room room1.room room1.room room1.room.hashCode()); System.out.println(room2.room room2.room room2.room room2.room.hashCode()); System.out.println(room3.room room3.room room3.room room3.room.hashCode()); System.out.println(room1 room1 room room1.hashCode()); System.out.println(room2 room2 room2 room2.hashCode()); System.out.println(room3 room3 room3 room3.hashCode()); } }从截图可以得知原型类与克隆类两者对应的成员变量的内存地址是一样的也就是说浅克隆时并未对原型类中的成员变量进行克隆具体原因是因为原型模式使用浅克隆时只复制它本身和其中包含的值类型的成员变量而引用类型的成员变量并不会去复制。原型模式深克隆import java.io.*; /** * author Evan Walker * version 1.0 * desc 深克隆工具类 昂焱数据: https://www.ayshuju.com * date 2023/04/10 20:38:47 */ public class CloneUtils { SuppressWarnings(unchecked) public static T extends Serializable T deepClone(T obj) { T cloneObj null; ObjectOutputStream obs null; ObjectInputStream ois null; try { //写入字节流 ByteArrayOutputStream out new ByteArrayOutputStream(); obs new ObjectOutputStream(out); obs.writeObject(obj); //分配内存写入原始对象生成新对象 ByteArrayInputStream ios new ByteArrayInputStream(out.toByteArray()); ois new ObjectInputStream(ios); //返回生成的新对象 cloneObj (T) ois.readObject(); } catch (Exception e) { e.printStackTrace(); } finally { //PS:ByteArrayOutputStream和ByteArrayInputStream其实是伪装成流的字节数组 // 把它们当成字节数据来看就好了 // 他们不会锁定任何文件句柄和端口如果不再被使用字节数组会被垃圾回收掉所以不需要关闭。 CloneUtils.close(obs); CloneUtils.close(ois); } return cloneObj; } /** * 关闭br * 关闭失败不会抛出异常 * * param closeable 被关闭的对象 */ public static void close(Closeable closeable) { if (null ! closeable) { try { closeable.close(); } catch (Exception e) { // 静默关闭 } } } }import java.io.Serializable; /** * author Evan Walker * version 1.0 * desc 深克隆测试类 昂焱数据: https://www.ayshuju.com * date 2023/04/10 14:25:26 */ public class Diary implements Serializable { private String author; private String content; private Diary diary; Override public String toString() { return Diary{ author author \ , content content \ , diary diary }; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author author; } public String getContent() { return content; } public void setContent(String content) { this.content content; } public Diary getDiary() { return diary; } public void setDiary(Diary diary) { this.diary diary; } public Diary() { } public Diary(String author, String content) { this.author author; this.content content; } public Diary(String author, String content, Diary diary) { this.author author; this.content content; this.diary diary; } public static void main(String[] args){ Diary diary new Diary(昂焱科技,深克隆测试); Diary diary1 new Diary(昂焱数据,深克隆测试,diary); Diary diary2 CloneUtils.deepClone(diary1); System.out.println(diary1.toString()); System.out.println(diary2.toString()); System.out.println(diary1.getDiary().hashCode() diary2.getDiary().hashCode()); System.out.println(diary1.hashCode() diary2.hashCode()); }所有属性都是一份拷贝, 跟原数据不会有任何耦合(不存在引用共享)原型模式简单实现方式简单实现方式包含三个角色:抽象原型Prototype:抽象原型类给出所有的具体原型所需要实现的拷贝方法的接口或者抽象类。具体原型ConcretePrototype:用于拷贝的原型实例实现了抽象原型Prototype所要求的接口。客户Client:客户端Client用来请求创建新的对象。抽象原型AbstratePrototype/** * author Evan Walker * version 1.0 * desc 形状抽象类 昂焱数据: https://www.ayshuju.com * date 2023/04/10 21:47:04 */ public abstract class Shape implements Cloneable { private String id; protected String type; abstract void describe(); public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id id; } Override public Object clone() { Object clone null; try { clone super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } Override public String toString() { return Shape{ id id \ , type type \ }; } }具体原型ConcretePrototype/** * author Evan Walker * version 1.0 * desc 形状原型具体实现类 昂焱数据: https://www.ayshuju.com * date 2023/04/10 21:49:49 */ public class Circle extends Shape { public Circle(){ type Circle; } Override void describe() { System.out.println(describe : Circle ); } } public class Rectangle extends Shape { public Rectangle(){ type Rectangle; } Override void describe() { System.out.println(describe : Rectangle); } } public class Square extends Shape { public Square(){ type Square; } Override void describe() { System.out.println(describe : Square); } }客户Client/** * author Evan Walker * version 1.0 * desc 原型测试 昂焱数据: https://www.ayshuju.com * date 2023/04/11 09:28:54 */ public class Client { public static void main(String[] args) { Square square new Square(); Square square1 (Square) square.clone(); System.out.println(square.toString() square.hashCode()); System.out.println(square1.toString() square1.hashCode()); Rectangle rectangle new Rectangle(); Rectangle rectangle1 (Rectangle) rectangle.clone(); System.out.println(rectangle.toString() rectangle.hashCode()); System.out.println(rectangle1.toString() rectangle1.hashCode()); Circle circle new Circle(); Circle circle1 (Circle) circle.clone(); System.out.println(circle.toString() circle.hashCode()); System.out.println(circle1.toString() circle1.hashCode()); } }原型模式登记实现方式简单实现方式包含三个角色:抽象原型Prototype抽象原型类给出所有的具体原型所需要实现的拷贝方法的接口或者抽象类。具体原型ConcretePrototype用于拷贝的原型实例实现了抽象原型Prototype所要求的接口。原型管理器PrototypeManager原型管理器PrototypeManager类中使用HashMap保存多个复制的原型对象供客户端Client类可以通过原型管理器中的get(String id) 方法获取复制的原型对象。客户Client客户端Client用来请求创建新的对象。抽象原型Prototype 同简单原型具体原型ConcretePrototype 同简单原型原型管理器PrototypeManagerimport java.util.concurrent.ConcurrentHashMap; /** * author Evan Walker * version 1.0 * desc 形状原型管理器 昂焱数据: https://www.ayshuju.com * date 2023/04/10 21:52:52 */ public class PrototypeManager { private static ConcurrentHashMapString, Shape shapeMap new ConcurrentHashMap(); /** * 根据形状id获取形状 * param shapeId 形状id * return */ public static Shape getShape(String shapeId) { Shape cachedShape shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } /** * 对形状进行一个简单的初始化 * shapeMap.put(shapeKey, shape); */ public static void loadCache() { Circle circle new Circle(); circle.setId(1); shapeMap.put(circle.getId(), circle); Square square new Square(); square.setId(2); shapeMap.put(square.getId(), square); Rectangle rectangle new Rectangle(); rectangle.setId(3); shapeMap.put(rectangle.getId(), rectangle); } }客户Client/** * author Evan Walker * version 1.0 * desc 原型测试 昂焱数据: https://www.ayshuju.com * date 2023/04/10 21:51:32 */ public class ClientTest { public static void main(String[] args) { PrototypeManager.loadCache(); Shape clonedShape PrototypeManager.getShape(1); System.out.println(Shape : clonedShape.getType()); Shape clonedShape2 PrototypeManager.getShape(2); System.out.println(Shape : clonedShape2.getType()); Shape clonedShape3 PrototypeManager.getShape(3); System.out.println(Shape : clonedShape3.getType()); } }原型模式的特点特点原型模式属于创建型模式原型模式要求原型类实现拷贝自身的接口,通过拷贝原型的实例来创建新的对象原型模式拷贝原型实例创建的新对象不需要关心对象本身的类型,只需要实现原型实例拷贝自身的方法,通过自定义的拷贝方法来创建新的对象,不需要通过new创建新的对象。优点克隆对象 而无需与它们所属的具体类相耦合。克隆预生成原型 避免反复运行初始化代码。更方便地生成复杂对象。用继承以外的方式来处理复杂对象的不同配置。缺点克隆包含循环引用的复杂对象可能会非常麻烦。原型模式需要为每一个类配置一个clone()方法。clone()方法在每个类的内部,当对已有类进行重构时,需要修改代码,违背了开闭原则。应用场景当需要复制一些对象同时又希望代码独立于这些对象所属的具体类可以使用原型模式。当一个类初始化需要消耗很多资源时有很多相似对象时可以设计一个原型通过对成员变量的些微修改来实现。如果子类的区别仅在于其对象的初始化方式当创建这些子类的目的是为了创建特定类型的对象时可使用该模式来减少子类的数量。Spring中原型bean的创建就是原型模式的应用。可以用深克隆的方式保存对象的状态比如实现撤销操作等。

相关新闻

视频修复实操:用 untrunc 修复截断 MP4 文件的完整流程

视频修复实操:用 untrunc 修复截断 MP4 文件的完整流程

视频修复实操:用 untrunc 修复截断 MP4 文件的完整流程 【免费下载链接】untrunc Restore a truncated mp4/mov. Improved version of ponchio/untrunc 项目地址: https://gitcode.com/gh_mirrors/un/untrunc MP4 文件录到一半就坏掉,往往让人无从…

2026/8/23 16:51:12 阅读更多 →
pgweb 完整指南:PostgreSQL 网页管理工具从建连到查数

pgweb 完整指南:PostgreSQL 网页管理工具从建连到查数

pgweb 完整指南:PostgreSQL 网页管理工具从建连到查数 【免费下载链接】pgweb Cross-platform client for PostgreSQL databases 项目地址: https://gitcode.com/gh_mirrors/pg/pgweb pgweb 是一个用 Go 编写的 PostgreSQL 网页管理工具,单个二进…

2026/8/23 21:36:56 阅读更多 →
c++编码规范

c++编码规范

Google C Style Guide是Google内部使用的C编程规范,旨在提高代码质量和一致性。它涵盖了命名规则、代码格式、编程实践等方面,以下是一些重要的规定: 1. 使用2个空格作为缩进,不要使用tab。 2. 大括号的使用:如果一个…

2026/8/23 21:38:48 阅读更多 →

最新新闻

一键激活Windows与Office,10分钟完成全部流程

一键激活Windows与Office,10分钟完成全部流程

一键激活Windows与Office,10分钟完成全部流程 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 屏幕右下角的激活水印挂了两周,Word 里的保存和排版按钮全是灰色。你试过找…

2026/8/24 16:02:08 阅读更多 →
QuickBMS 游戏资源提取指南:任意存档包,一条命令搞定

QuickBMS 游戏资源提取指南:任意存档包,一条命令搞定

QuickBMS 游戏资源提取指南:任意存档包,一条命令搞定 【免费下载链接】QuickBMS QuickBMS by aluigi - Github Mirror 项目地址: https://gitcode.com/gh_mirrors/qui/QuickBMS 你下载的游戏资源包打不开?专用提取器只认某一款游戏&a…

2026/8/24 16:02:08 阅读更多 →
IDM 试用期重置完整指南:三步突破注册表权限壁垒,免费恢复30天试用

IDM 试用期重置完整指南:三步突破注册表权限壁垒,免费恢复30天试用

IDM 试用期重置完整指南:三步突破注册表权限壁垒,免费恢复30天试用 【免费下载链接】idm-trial-reset Use IDM forever without cracking 项目地址: https://gitcode.com/gh_mirrors/id/idm-trial-reset 当你第三次看到"试用期已过期"的…

2026/8/24 16:02:08 阅读更多 →
基于LLM与Whisper的本地化AI字幕翻译工具链实践

基于LLM与Whisper的本地化AI字幕翻译工具链实践

这次我们来看一个本地部署的 AI 字幕翻译工具链实践。项目本身是一个名为“科学冒险队Tansar5 1979”的视频,但核心价值在于其配套的“DeepSeek英转中文字幕”工作流程。这背后涉及的不是单一软件,而是一套将英文视频或SRT字幕文件,通过大语言…

2026/8/24 16:02:08 阅读更多 →
Unlock Music 实操指南:在浏览器里用 5 分钟完成加密音乐文件解密

Unlock Music 实操指南:在浏览器里用 5 分钟完成加密音乐文件解密

Unlock Music 实操指南:在浏览器里用 5 分钟完成加密音乐文件解密 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目…

2026/8/24 16:02:08 阅读更多 →
基于大语言模型的AI字幕翻译实践:从SRT处理到本地化工作流

基于大语言模型的AI字幕翻译实践:从SRT处理到本地化工作流

这次我们来看一个将经典动画《万能战士无比敌》(无敌侠)1980版进行AI字幕翻译的项目。这个项目的核心不是开发新模型,而是利用DeepSeek这类大语言模型的能力,对已有的英文字幕文件进行高质量、风格化的中文翻译,最终生…

2026/8/24 16:01:08 阅读更多 →

日新闻

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践 前端安全依赖分层防护。没有任何单一配置能替代输出编码、权限校验和依赖更新。 把不可信内容当作数据 默认使用框架的转义能力;确需渲染 HTML 时,先在服务端或可信的客户端库中进行白名单过滤。避免把用户输入直接赋给 inne…

2026/8/24 1:08:15 阅读更多 →
Windows登录密码存储机制全解析:从哈希算法到安全加固实战

Windows登录密码存储机制全解析:从哈希算法到安全加固实战

1. 项目概述:Windows登录密码的“黑匣子”每次你按下CtrlAltDel,输入密码,然后看到那个熟悉的桌面,这背后发生了一系列复杂而精密的操作。作为一名长期与Windows系统打交道的从业者,我经常被问到:“我的密码…

2026/8/24 1:08:15 阅读更多 →
AI面试系统安全挑战与解决方案

AI面试系统安全挑战与解决方案

1. 项目概述:AI面试系统的安全挑战去年参与某跨国企业AI面试系统部署时,遇到一个典型案例:候选人在视频面试中无意提到竞争对手产品名称,系统竟自动将该信息关联到企业知识库并生成竞品分析报告。这个看似"智能"的功能&…

2026/8/24 1:08:15 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/24 11:20:22 阅读更多 →