【设计模式】从零开始,用原型模式简化你的Java对象创建过程!

概述

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。

结构

原型模式包含如下角色:

  • 抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。

  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。

  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

接口类图如下:

实现

原型模式的克隆分为浅克隆和深克隆。

浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

Java中的Object类中提供了 clone() 方法来实现浅克隆。 Cloneable 接口是上面的类图中的抽象原型类,而实现了Cloneable接口的子实现类就是具体的原型类。代码如下:

Realizetype(具体的原型类):

public class Realizetype implements Cloneable {public Realizetype() {System.out.println("具体的原型对象创建完成!");}@Overrideprotected Realizetype clone() throws CloneNotSupportedException {System.out.println("具体原型复制成功!");return (Realizetype) super.clone();}
}

PrototypeTest(测试访问类):

public class PrototypeTest {public static void main(String[] args) throws CloneNotSupportedException {Realizetype r1 = new Realizetype();Realizetype r2 = r1.clone();System.out.println("对象r1和r2是同一个对象?" + (r1 == r2));}
}

案例

用原型模式生成“三好学生”奖状

同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,可以使用原型模式复制多个“三好学生”奖状出来,然后在修改奖状上的名字即可。

类图如下:

代码如下:

//奖状类
public class Citation implements Cloneable {private String name;public void setName(String name) {this.name = name;}public String getName() {return (this.name);}public void show() {System.out.println(name + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");}@Overridepublic Citation clone() throws CloneNotSupportedException {return (Citation) super.clone();}
}//测试访问类
public class CitationTest {public static void main(String[] args) throws CloneNotSupportedException {Citation c1 = new Citation();c1.setName("张三");//复制奖状Citation c2 = c1.clone();//将奖状的名字修改李四c2.setName("李四");c1.show();c2.show();}
}

使用场景

  • 对象的创建非常复杂,可以使用原型模式快捷的创建对象。

  • 性能和安全要求比较高。

扩展(深克隆)

将上面的“三好学生”奖状的案例中Citation类的name属性修改为Student类型的属性。代码如下:

//奖状类
public class Citation implements Cloneable {private Student stu;public Student getStu() {return stu;}public void setStu(Student stu) {this.stu = stu;}void show() {System.out.println(stu.getName() + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");}@Overridepublic Citation clone() throws CloneNotSupportedException {return (Citation) super.clone();}
}//学生类
public class Student {private String name;private String address;public Student(String name, String address) {this.name = name;this.address = address;}public Student() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}//测试类
public class CitationTest {public static void main(String[] args) throws CloneNotSupportedException {Citation c1 = new Citation();Student stu = new Student("张三", "西安");c1.setStu(stu);//复制奖状Citation c2 = c1.clone();//获取c2奖状所属学生对象Student stu1 = c2.getStu();stu1.setName("李四");//判断stu对象和stu1对象是否是同一个对象System.out.println("stu和stu1是同一个对象?" + (stu == stu1));c1.show();c2.show();}
}

运行结果为:

说明:stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个Citation(奖状)对象中显示的都是李四。这就是浅克隆的效果,对具体原型类(Citation)中的引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流。代码如下:

public class CitationTest1 {public static void main(String[] args) throws Exception {Citation c1 = new Citation();Student stu = new Student("张三", "西安");c1.setStu(stu);//创建对象输出流对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\Think\\Desktop\\b.txt"));//将c1对象写出到文件中oos.writeObject(c1);oos.close();//创建对象出入流对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\Think\\Desktop\\b.txt"));//读取对象Citation c2 = (Citation) ois.readObject();//获取c2奖状所属学生对象Student stu1 = c2.getStu();stu1.setName("李四");//判断stu对象和stu1对象是否是同一个对象System.out.println("stu和stu1是同一个对象?" + (stu == stu1));c1.show();c2.show();}
}

运行结果为:

注意:Citation类和Student类必须实现Serializable接口,否则会抛NotSerializableException异常。

往期推荐

  • 《SpringBoot》EasyExcel实现百万数据的导入导出
  • 《SpringBoot》史上最全SpringBoot相关注解介绍
  • Spring框架IoC核心详解
  • 万字长文带你窥探Spring中所有的扩展点
  • 如何实现一个通用的接口限流、防重、防抖机制
  • 万字长文带你深入Redis底层数据结构
  • volatile关键字最全原理剖析

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

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

相关文章

SWPU CTF 2023 秋季新生赛 If_else

题干 访问首页,源码如下 <?php $a=false; $b=false; if(你提交的部分将会被写至这里) {$a=true;} else {$b=true;} if($a===true&&$b===true) eval(system(cat /flag)); ?>分析源码发现,通过post方式传递check参数,如果该值既满足true又满足f…

**20242802 2024-2025-2 《网络攻防实践》第一周作业**

20242802 2024-2025-2 《网络攻防实践》第一周作业 1.知识点梳理与总结 1.1 相关知识点与总结 因为在本课之前我没有学习过网络攻防的相关知识,在第一次实验前我先阅读了课程资料中第0章和第1章的内容结合网络资料,我对本门课程有了大致的理解:学习网络攻防知识作为网络安全…

20242924 《网络攻防实践》第1周作业

20242924 任雯楚《网络攻防实践》 第1周作业 1.知识点梳理与总结 1.1 VMware Workstation 多系统并行运行:在单台物理机上同时部署多个虚拟机(如 Kali 攻击机、Metasploitable 靶机),支持 Windows/Linux 等异构系统共存。 1.2 虚拟机镜像 虚拟机镜像是一种虚拟机的文件,它…

180多页详细解读多元化AI!清华大学《AIGC发展研究》

180多页详细解读多元化AI!清华大学《AIGC发展研究》无论是最初的ChatGPT还是目前大火的DeepSeek,底层都依赖于从于自然语言处理(NLP)、计算机视觉(CV)等先进的人工智能技术。无论是从最初的文本生成域到视频生成域以及现在逻辑推理领域都是从语料预训练→模型训练→参数学…

读DAMA数据管理知识体系指南11数据建模(下)

数据建模包括规范化、抽象化,规划成果,建立模型(含正向、逆向工程),涉及范式层次、抽象方法、图表定义、血缘追踪、持续改进及逻辑物理建模等。1. 规范化 1.1. 规范化(Normalization)是运用规则将复杂的业务转化为规范的数据结构的过程 1.2. 范式化的基本目标是保证每个属…

The Ethernaut题解

Level_0.Hello Ethernaut安装MetaMask; F12中的Console,一些指令查看state:查看自己的钱包地址->player:查看余额->getBalance(player):查看合约->ethernaut:合约交互,比如查看合约的owner->ethernaut.owner():从水龙头处获得ETH:(可以Sepolia PoW Faucet挖,也可以…

CAN通信

一.什么是CAN总线 1.CAN总线的概念CAN总线(Controller Area Network Bus)控制器局域网总线2.CAN总线的特点 3.常见通信协议对比(UART、IC、SPI、CAN)特性 UART IC SPI CAN全称 Universal Asynchronous Receiver/Transmitter Inter-Integrated Circuit Serial Peripheral In…

typora图床搭建+完美解决PicGo图片上传重命名问题

typora图床搭建+完美解决PicGo图片上传重命名问题typora图床搭建+完美解决PicGo图片上传重命名问题 typora设置上图中第五步需要你下载PicGo应用并安装 PicGo配置 下载安装好后得到如图界面这时需要对该软件进行配置 文档在这里https://picgo.github.io/PicGo-Doc/zh/guide/con…

[NSSCTF 2022 Spring Recruit]ezgame(两种解法)

可以看到,这个题目一打开就是一道简单的小游戏,玩了一会没看到什么提示就打开页面源码看看有没有提示可以看到只要分数超过65就会告诉你flag,但是真的自己去玩基本上是玩不到65分的,于是我尝试修改页面代码看能不能绕过 解法1 由于页面爆炸了,这里就不附上截图,反正修改分…

【转载】VPS、ECS、Docker和k8s

图片及内容均来源于小林coding公众号:面试官:Docker 和 k8s 之间是什么关系? 物理服务器 一台看得见摸得着的机器,其实就是云厂商页面里提到的物理服务器或物理机。不同厂商叫法不同,有的厂商叫它独立服务器。 vps 和 ecs VPS(Virtual Private Server,虚拟专用服务器)。…

【云原生】VPS、ECS、Docker和k8s

图片及内容均来源于小林coding公众号:面试官:Docker 和 k8s 之间是什么关系? 物理服务器 一台看得见摸得着的机器,其实就是云厂商页面里提到的物理服务器或物理机。不同厂商叫法不同,有的厂商叫它独立服务器。 vps 和 ecs VPS(Virtual Private Server,虚拟专用服务器)。…

FastAPI 查询参数完全指南:从基础到高级用法

title: FastAPI 查询参数完全指南:从基础到高级用法 🚀 date: 2025/3/6 updated: 2025/3/6 author: cmdragon excerpt: 探讨 FastAPI 查询参数的核心机制,涵盖从必需与可选参数、默认值到多参数处理的全方位知识。通过详细的代码示例、课后测验和常见错误解决方案,通过类…