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

原型模式(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,一经查实,立即删除!

相关文章

spring mvc源码学习笔记之八

本文说点儿简单的。 如果你想研究基于 XML 配置的 spring mvc 的话,可以简单扫一眼本文。 在基于 XML 配置的 spring mvc 开发中,我们主要就是通过 spring 提供的各种标签来配置。 但是,大家是不是都有个疑问,spring 到底给我们提…

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…

导航技术的分类

导航技术可以根据不同的分类标准进行划分,以下是从不同角度对导航技术的分类: 一、按导航信息获取原理分类 无线电导航:利用无线电波的传播特性来测定运动体的位置、速度等导航参数。常见的无线电导航系统包括罗兰-C、奥米加、台卡等。卫星…

【Python3】异步操作 redis

aioredis 在高版本已经不支持了, 不要用 代码示例 redis 连接池异步操作redis以及接口 import asyncio from sanic import Sanic from sanic.response import json import redis.asyncio as redis from redis.asyncio import ConnectionPool# 创建 Sanic 应用 app…

Vue3 混入(Mixins)

Vue3 混入(Mixins) 引言 在Vue3中,混入(Mixins)是一种提供可复用功能的方式。通过混入,我们可以将组件的逻辑抽离出来,以便在多个组件之间共享。Vue3的混入机制与Vue2类似,但在某些方面进行了优化和改进。本文将详细介绍Vue3中混入的使用方法、注意事项以及最佳实践。…

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

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

C语言的语法

C语言的语法与应用探讨 C语言作为一种高效的程序设计语言,自1970年代问世以来,一直在科学计算、系统编程、嵌入式系统等领域中扮演着重要角色。本文将深入探讨C语言的基本语法、数据结构、控制结构以及其在实际应用中的重要性。 一、C语言基础 1.1 数…

【AI工具】PDFMathTranslate安装使用

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

Ubuntu 上安装 Docker

在Ubuntu上安装Docker的步骤如下: 1. 更新系统 首先,更新系统的软件包索引: sudo apt update2. 安装必要的依赖包 接着,安装一些必要的依赖包,用于安装Docker的官方仓库: sudo apt install apt-transp…

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…

【生物信息】如何使用 h5py 读取 HDF5 格式文件中的数据并将其转换为 NumPy 数组

data_mat h5py.File(args.data_file) x1 np.array(data_mat[X1]) x2 np.array(data_mat[X2]) if not args.no_labels: y np.array(data_mat[Y]) data_mat.close() 这段代码展示了如何使用 h5py 读取 HDF5 格式文件中的数据并将其转换为 NumPy 数组。以下是代码的详细解释&a…

计算机网络 (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;例…