二十三种设计模式-原型模式

原型模式(Prototype Pattern)是一种创建型设计模式,它通过拷贝现有的实例来创建新的实例,而不是通过新建实例。这种方式可以避免复杂的构造过程,同时还能保持对象的创建和使用分离,提高系统的灵活性和扩展性。

了解原型模式之前需要先搞懂浅拷贝和深拷贝。

浅拷贝指的是创建一个新对象,然后将原对象的非静态字段复制到新对象中。如果字段是基本数据类型,那么直接复制其值;如果字段是对象引用,则复制引用本身,而不是引用的对象。这意味着新对象和原对象的引用字段指向同一个对象。

深拷贝意味着不仅要复制对象本身,还要复制对象中所有引用的对象,以及这些引用对象中引用的其他对象,直到所有相关对象都被复制。

另外java中有一些特殊的引用类型(不可变对象),如下。这些引用类型创建的对象是不可变对象,在拷贝是都是理解成是一种深拷贝。

在Java中,不可变对象是指一旦创建后,其状态(即对象的字段值)就不能被改变的对象。不可变对象具有线程安全性、可缓存性和可共享性等优点。以下是一些常见的不可变引用类型对象:基本数据类型的包装类
Integer
Byte
Short
Long
Float
Double
Character
Boolean
这些包装类都是基本数据类型的对应引用类型。它们是不可变的,因为它们的值一旦被设置,就不能被改变。例如,当你对一个Integer对象进行加法运算时,实际上会创建一个新的Integer对象来表示新的值,而不是修改原来的对象。字符串类
String
String类是Java中最常用的不可变类之一。字符串对象一旦被创建,其内容就不能被改变。例如,当你使用+操作符连接两个字符串时,会创建一个新的字符串对象,而不是修改原来的字符串对象。原子类
AtomicInteger
AtomicLong
AtomicBoolean
其他java.util.concurrent.atomic包中的原子类
这些原子类提供了对基本数据类型的安全操作,它们是不可变的,因为它们的值只能通过原子操作来更新,而不是直接修改对象的状态。其他不可变类
BigDecimal 和 BigInteger
这些类用于表示任意精度的数值。它们是不可变的,因为每次进行数学运算时,都会返回一个新的对象来表示结果,而不是修改原来的对象。java.time包中的日期和时间类
例如:LocalDate
LocalTime
LocalDateTime
ZonedDateTime
Duration
Period
这些类是Java 8引入的新的日期和时间API的一部分。它们都是不可变的,每次进行日期或时间的修改操作时,都会返回一个新的对象。不可变对象的设计原则
要设计一个不可变对象,通常需要遵循以下原则:所有字段都是final的:确保字段一旦被初始化,就不能被改变.
不提供修改字段值的方法:不提供任何可以修改对象状态的方法.
确保对象的所有字段都是不可变的:如果对象的字段是引用类型,确保这些引用类型也是不可变的.
如果需要提供访问字段的方法,返回字段的副本而不是引用:例如,对于包含可变对象的字段,返回字段的副本,以防止外部代码修改对象的状态.
通过设计不可变对象,可以提高程序的安全性和可维护性,特别是在多线程环境中.

原型模式核心概念

  • 原型(Prototype):声明一个克隆自身的接口,用于创建当前对象的副本。在Java中,通常通过实现Cloneable接口并重写clone()方法来实现原型模式。
  • 具体原型(ConcretePrototype):实现原型接口,提供具体的克隆实现,生成自己的副本。

实现步骤

  1. 实现Cloneable接口:让类实现Cloneable接口,表示该类的对象可以被克隆。
  2. 重写clone()方法:在类中重写Object类的clone()方法,以实现深拷贝或浅拷贝。
  3. 创建原型对象:创建一个原型对象,作为后续克隆的模板。
  4. 克隆原型对象:通过调用原型对象的clone()方法,创建新的对象实例.

示例代码

以下是一个简单的Java示例,展示如何使用原型模式:

import java.util.Date;// 具体原型类
class Resume implements Cloneable {private String name;private String sex;private String age;private Date birthDate; // 假设包含日期对象public Resume(String name, String sex, String age) {this.name = name;this.sex = sex;this.age = age;this.birthDate = new Date(); // 初始化日期对象}@Overrideprotected Object clone() throws CloneNotSupportedException {// 实现深拷贝//super.clone()是调用Object类的clone()方法,它会创建一个新的对象,并将原对象的字段值复制到新对象中。对于基本数据类型的字段,值会被直接复制;而对于引用类型的字段,复制的是引用本身,而不是引用所指向的对象. 这一步本身是浅拷贝.Resume clonedResume = (Resume) super.clone();clonedResume.birthDate = (Date) this.birthDate.clone();return clonedResume;}@Overridepublic String toString() {return "Resume{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", age='" + age + '\'' +", birthDate=" + birthDate +'}';}
}public class PrototypePatternDemo {public static void main(String[] args) throws CloneNotSupportedException {Resume originalResume = new Resume("John Doe", "Male", "30");System.out.println("Original Resume: " + originalResume);Resume clonedResume = (Resume) originalResume.clone();System.out.println("Cloned Resume: " + clonedResume);}
}

优缺点

  • 优点
    • 性能优势:通过拷贝现有对象,避免了复杂的构造过程,特别是在对象创建过程中需要进行大量数据计算或资源获取时.
    • 代码简洁:简化了对象的创建代码,使得代码更加简洁和易于维护.
  • 缺点
    • 实现复杂:需要实现深拷贝,对于包含复杂对象引用的类,实现起来可能比较复杂.
    • 对类的约束:需要实现Cloneable接口,并且所有涉及的对象都需要支持拷贝操作,这可能对类的设计有一定的约束.

适用场景

  • 当一个系统应该独立于其产品的创建、组合和表示时.
  • 当需要通过动态指定创建对象的类别、数目和初始化参数时.
  • 当对象的创建过程复杂,且需要避免重复创建大量相似对象时.

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

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

相关文章

php命名空间

什么是命名空间 从广义上来说,命名空间是一种封装事物的方法,在很多地方都可以见到这种抽象概念。 例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。 具体举个例子&#xf…

【Unity3D】导出Android项目以及Java混淆

Android Studio 下载文件归档 | Android Developers Android--混淆配置(比较详细的混淆规则)_android 混淆规则-CSDN博客 Unity版本:2019.4.0f1 Gradle版本:5.6.4(或5.1.1) Gradle Plugin版本&#xff…

腾讯云AI代码助手编程挑战赛-每日一句

一、作品简介 “每日一句”是一个基于Python的图形用户界面(GUI)应用程序,旨在为用户提供随机的中英文名言警句。它利用腾讯云AI代码助手辅助开发,为用户带来便捷、高效的阅读体验。 二、技术架构 1. 编程语言:使用P…

【AI工具】PDFMathTranslate安装使用

用了一天时间,安装并使用了PDFMathTranslate这款PDF文档翻译工具。 PDFMathTranslate是能够完整保留排版的 PDF 文档全文双语翻译项目,之前使用文档翻译的时候,对于论文这种类型的文章,由于图表和公式太多,文档翻译经常…

conda 批量安装requirements.txt文件

conda 批量安装requirements.txt文件中包含的组件依赖 conda install --yes --file requirements.txt #这种执行方式,一遇到安装不上就整体停止不会继续下面的包安装。 下面这条命令能解决上面出现的不执行后续包的问题,需要在CMD窗口执行: 点…

网络安全图谱以及溯源算法

​ 本文提出了一种网络攻击溯源框架&#xff0c;以及一种网络安全知识图谱&#xff0c;该图由六个部分组成&#xff0c;G <H&#xff0c;V&#xff0c;A&#xff0c;E&#xff0c;L&#xff0c;S&#xff0c;R>。 1|11.知识图 ​ 网络知识图由六个部分组成&#xff0c…

上汽乘用车研发流程

目的 最近刚入职主机厂&#xff0c;工作中所提到各个阶段名称与之前在供应商那边不一致&#xff0c;概念有点模糊&#xff0c;所以打算学习了解一番 概念 术语 EP: enginerring prototype car 工程样车 Mule Car: 骡子车 Simulator Car&#xff1a;模拟样车 PPV&#xff1a;…

封装/前线修饰符/Idea项目结构/package/impore

目录 1. 封装的情景引入 2. 封装的体现 3. 权限修饰符 4. Idea 项目结构 5. package 关键字 6. import 关键字 7. 练习 程序设计&#xff1a;高内聚&#xff0c;低耦合&#xff1b; 高内聚&#xff1a;将类的内部操作“隐藏”起来&#xff0c;不需要外界干涉&#xff1b…

计算机网络 (23)IP层转发分组的过程

一、IP层的基本功能 IP层&#xff08;Internet Protocol Layer&#xff09;是网络通信模型中的关键层&#xff0c;属于OSI模型的第三层&#xff0c;即网络层。它负责在不同网络之间传输数据包&#xff0c;实现网络间的互联。IP层的主要功能包括寻址、路由、分段和重组、错误检测…

【W800】UART 的使用与问题

1.开发环境 OS: Windows 11开发板&#xff1a;海凌科 HLK-W800-KIT-PROSDK: W80X_SDK_v1.00.10IDE: CSKY Development Kit 2.UART 使用 在 SDK 中创建文件 uart_test.h 和 uart_test.c&#xff0c;然后在 CDK 项目中添加这两个文件&#xff0c;CDK 会自动 include 头文件。 …

万界星空科技质量管理QMS系统具体功能介绍

一、什么是QMS系统&#xff0c;有什么价值&#xff1f; 1、QMS 系统即质量管理系统&#xff08;Quality Management System&#xff09;。 它是一套用于管理和控制企业产品或服务质量的集成化体系。 2、QMS 系统的价值主要体现在以下几个方面&#xff1a; 确保产品质量一致性…

【C++】B2099 矩阵交换行

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述题目描述输入格式输出格式输入输出样例输入 #1输出 #1 &#x1f4af;题目分析&#x1f4af;不同解法分析我的做法实现步骤&#xff1a;优点&#xff1a;不足&#…

Tableau数据可视化与仪表盘搭建-数据连接

目录 连接本地文件 课程操作 连接方式&#xff08;实时/数据提取&#xff09; 保存工作簿 筛选器 数据处理 连接数据有三种类型 第一种&#xff0c;连接到本地文件&#xff0c;例如Excel&#xff0c;csv&#xff0c;JSON等 第二种&#xff0c;连接到数据库&#xff0c;例…

系统日志优化---自定义springboot-starter日志组件供各个服务使用

在优化项目时发现各个微服务都有各自的接口调用日志逻辑&#xff0c;比如每个服务都定义一个aop类拦截&#xff0c;十分冗余&#xff0c;其实是可以做成starter被各个服务引用使用&#xff0c;前提要先了解一下springboot自动装配原理 创建springboot工程&#xff0c;如果是jdk…

Android V QCOM GPS | APN for LocationService

问题 在高通平台上验证 GPS 功能流程时候,block 在 APN 数据库的查询。经查,发现高通有内部实现的 LocationService(aosp源码和mtk都没有的类) 包含查询 TelephonyProvider 数据库的逻辑,直接原因是查询到 APN Protocol 不符合预期,直接fail。 关于 Android APN 数据列的…

基于 Apache Commons Pool 实现的 gRPC 连接池管理类 GrpcChannelPool 性能分析与优化

基于 Apache Commons Pool 实现的 gRPC 连接池管理类 GrpcChannelPool 性能分析与优化 1. 输出关键信息的代码示例 日志记录方法 使用以下代码记录连接池的关键信息&#xff0c;帮助分析连接池的状态和性能瓶颈&#xff1a; import org.apache.commons.pool2.impl.GenericO…

小程序开发-页面事件之上拉触底实战案例

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

STM32-笔记38-I2C-oled实验

一、什么是I2C&#xff1f; I2C总线&#xff0c;全称Inter-Integrated Circuit&#xff08;互连集成电路&#xff09;&#xff0c;是一种由Philips&#xff08;现NXP半导体&#xff09;公司在1980年代初开发的同步 串行 半双工通信总线。 二、有了串口通信为什么要使用I2C&…

《C++11》右值引用深度解析:性能优化的秘密武器

C11引入了一个新的概念——右值引用&#xff0c;这是一个相当深奥且重要的概念。为了理解右值引用&#xff0c;我们需要先理解左值和右值的概念&#xff0c;然后再理解左值引用和右值引用。本文将详细解析这些概念&#xff0c;并通过实例进行说明&#xff0c;以揭示右值引用如何…

libevent定时器的性能测试(与rte_timer对比)

前言 接着上篇文章&#xff0c;rte_timer的性能测试https://blog.csdn.net/jacicson1987/article/details/144997298 进行常用的libevent的定时器测试&#xff0c;看看有什么区别&#xff0c;测试方法还是一样&#xff0c;代码放在下面。 测试方法 100万个定时器&#xff0…