当前位置: 首页 > news >正文

原型设计模式

介绍

原型模式

在Java中,原型模式是一种创建型设计模式,它允许通过复制一个现有对象来创建一个新对象,而不是通过创建新的对象来初始化一个对象,原型模式是一种基于克隆的设计模式,通过复制现有对象的数据来创建新的对象.

原型模式需要实现Cloneable接口并重写Object类中的clone()方法,在重谢clone()方法时,需要调用super.clone()方法来创建一个新的对象,并复制原始对象中的所有属性.默认情况下,Java中的Object类提供的clone()方法会执行浅拷贝,如果原始对象中包含引用类型的成员变量,则需要进行深拷贝操作,以确保新对象中所有成员变量都是独立的.

深拷贝与浅拷贝

浅拷贝(Shallow Copy)会创建一个新的对象,该对象具有与原始对象相同的属性值.但是,如果原始对象包含对其他对象的引用,则新对象也将包含对相同对象的引用.换句话说,新对象仅仅是原始对象的一个副本,而不是独立的对象.

深拷贝(Deep Copy)则是创建一个新的对象,该对象具有与原始对象相同的属性值,但是它会递归的复制对象图中所有的对象,而不是只复制引用.换句话说,深拷贝会创建一个完全独立的新对象,该对象与原始对象没有任何关联.

区别:

  • 对于基本数据类型,浅拷贝和深拷贝没有区别,因为基本数据类型在内存中储存为值.但是对于引用类型,浅拷贝和深拷贝会有不同的行为.浅拷贝只复制对象本身以及其中的基本数据类型成员,而不会复制引用类型成员.因此,如果原始对象中包含引用类型成员,浅拷贝得到的对象中的引用类型成员与原始对象中的相同,即两者指向同一块内存地址.而深拷贝则会递归的复制所有的引用类型成员,因此得到的对象中的引用类型成员与原始对象中的不同,即两者指向不同的内存地址.
  • 浅拷贝速度相对较快,因为它只复制了对象本身以及其中的基本数据类型成员.而深拷贝速度相对较慢,因为它需要递归的复制所有引用类型成员.

应用场景:

  • 浅拷贝通常用于快速创建对象副本,且原始对象中不包含引用类型成员的情况下,可以使用浅拷贝.比如,当需要多个对象共享某些状态时,可以使用浅拷贝来快速创建副本
  • 深拷贝通常用于创建完全独立的对象,且原始对象中包含引用类型成员的情况下,可以使用深拷贝

浅拷贝示例代码

@Data
public class Person implements Cloneable{private String name;private int age;private Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}@Data
public class Address {private String city;private String street;public Address(String city, String street) {this.city = city;this.street = street;}
}

测试浅拷贝

package com.fanqiechaodan.prototype.copy.shollow;import com.alibaba.fastjson.JSON;/*** @author fanqiechaodan* @Classname Demo* @Description 浅拷贝* @Date 2023/3/10 18:59*/
public class Demo {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person("张三", 18, new Address("上海", "南京路"));Person person2 = (Person) person1.clone();System.out.println(JSON.toJSONString(person1));System.out.println(JSON.toJSONString(person2));System.out.println("浅拷贝后:");person1.getAddress().setCity("南京");System.out.println(JSON.toJSONString(person1));System.out.println(JSON.toJSONString(person2));}
}

在这里插入图片描述

深拷贝示例代码

@Data
public class Person implements Serializable {private String name;private int age;private Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overrideprotected Object clone() {try {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}return null;}
}@Data
public class Address implements Serializable {private String city;private String street;public Address(String city, String street) {this.city = city;this.street = street;}
}

测试深拷贝

package com.fanqiechaodan.prototype.copy.deep;import com.alibaba.fastjson.JSON;
import org.springframework.util.SerializationUtils;import java.io.IOException;/*** @author fanqiechaodan* @Classname Demo* @Description 深拷贝* @Date 2023/3/10 19:15*/
public class Demo {public static void main(String[] args) throws IOException, ClassNotFoundException {Person person1 = new Person("张三", 18, new Address("上海", "南京路"));// 重写clone完成深拷贝Person person2 = (Person) person1.clone();// 使用工具类完成深拷贝Person person3 = (Person) SerializationUtils.deserialize(SerializationUtils.serialize(person1));System.out.println(JSON.toJSONString(person1));System.out.println(JSON.toJSONString(person2));System.out.println(JSON.toJSONString(person3));System.out.println("深拷贝后:");person1.getAddress().setCity("南京");System.out.println(JSON.toJSONString(person1));System.out.println(JSON.toJSONString(person2));System.out.println(JSON.toJSONString(person3));}
}

在这里插入图片描述

原型模式代码

原型类代码

@Data
public class Person implements Cloneable{private String name;private int age;private Address address;public Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}@Data
public class Address {private String city;private String street;public Address(String city, String street) {this.city = city;this.street = street;}
}

测试

package com.fanqiechaodan.prototype;import com.alibaba.fastjson.JSON;/*** @author fanqiechaodan* @Classname Demo* @Description* @Date 2023/3/10 19:23*/
public class Demo {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person("张三", 18, new Address("北京", "青年路"));Person person2 = (Person) person1.clone();System.out.println(JSON.toJSONString(person1));System.out.println(JSON.toJSONString(person2));}
}

在这里插入图片描述

需要注意的是,在使用Cloneable接口实现原型模式时,需要注意以下几点:

  1. 要使用克隆方法,必须确保该对象实现了Cloneable接口.否则,在调用clone方法时会抛出CloneNotSupportedException异常
  2. 调用clone方法返回的是一个浅拷贝对象,如果对象包含了引用类型的成员变量,那么这些成员变量依然会被多个对象共享.
  3. 在实现clone方法时,需要注意对成员变量的处理,特别是对引用类型的成员变量的处理.如果需要实现深拷贝,可以通过重写clone方法来实现.

总结

优点:

  • 减少了重复代码的编写,避免了创建大量相似对象的开销,提高了系统的性能.
  • 可以动态的创建对象,而不是静态地在代码中定义,更加灵活.
  • 简化了对象的创建过程,减少了不必要的参数传递.

缺点:

  • 由于原型模式会复制对象,可能导致对象状态的改变,因此需要谨慎处理.
  • 由于原型模式使用了克隆的方式创建对象,可能导致类的层次结构比较复杂.

应用场景:

  • 当需要创建大量相似的对象时,使用原型模式可以大大减少对象创建的开销.
  • 当对象的创建过程比较复杂,或者对象的状态会随着时间的推移而发生改变时,可以考虑使用原型模式.
  • 当需要动态地创建对象时,可以使用原型模式.例如:在运行时动态创建新对象或者在数据库中读取对象并创建新对象.

相关文章:

原型设计模式

介绍 原型模式 在Java中,原型模式是一种创建型设计模式,它允许通过复制一个现有对象来创建一个新对象,而不是通过创建新的对象来初始化一个对象,原型模式是一种基于克隆的设计模式,通过复制现有对象的数据来创建新的对象. 原型模式需要实现Cloneable接口并重写Object类中的c…...

JVM结构-类加载(类加载子系统,类加载的角色,类加载的过程,类加载器分类,双亲委派机制,类的主/被动使用)

JVM 结构-类加载2.1类加载子系统2.2类加载的角色2.3类加载的过程2.3.1加载2.3.2链接2.3.3初始化2.4类加载器分类2.4.1 引导类加载器2.4.2扩展类加载器2.4.3应用程序类加载器2.5双亲委派机制2.6类的主动/被动使用2.1类加载子系统 类加载器子系统负责从文件系统或者网络中加载 cl…...

vcpkg私有port的创建和使用

1,准备环境: 系统:windows 系统 2, 安装vcpkg 步骤一 :先git clone下载下来vcpkg文件夹 命令:git clone “https://github.com/Microsoft/vcpkg.git” 步骤二:添加vcpkg环境变量 例如下载目录:D:\woker_zj 步骤三:编译vcpkg 操作:双击bootstrap-vcpkg.bat 步骤四: 为…...

LeetCode——203. 移除链表元素

对于初学链表的学者来学,链表是比较困难的,这部分对指针结构体的要求比较高。我们通过练习是掌握知识的重要途经203. 移除链表元素 - 力扣(LeetCode)我们在数组中去除某元素是遍历一遍数组,如果某位置是要去除的元素&a…...

[Java Web]Request对象 | 超1w字带你熟悉Servlet中的request请求

⭐作者介绍:大二本科网络工程专业在读,持续学习Java,输出优质文章 ⭐所属专栏:Java Web ⭐如果觉得文章写的不错,欢迎点个关注😉有写的不好的地方也欢迎指正,一同进步😁 目录 Reque…...

求一个补码表示数的原始值的三种方式

求一个补码表示数的原始值的三种方式假设 a(10010)2′complement−14a (10010)_{2complement}-14a(10010)2′complement​−14 方式1,通过补码求原始值公式求值(see article) x−xM−1∗2M−1∑i0M−2xi∗2ix-x_{M-1}*2^{M-1}\sum_{i0}^{M-2…...

【计算机组成原理】

第2章 运算方法和运算器 2.1 数据与文字的表示方法 2.1.1 数据格式 定点数的表示方法 定点纯小数纯小数表示范围定点纯整数定点表示法特点 浮点数的表示方法: 浮点的规格化表示:阶码、尾数、指数、基数IEEE754标准:单精度、双精度浮点数表…...

论文分享:图像识别与隐私安全

1、基于差分隐私框架的频域下人脸识别隐私保护算法Privacy-Preserving Face Recognition with Learnable Privacy Budget in Frequency Domain2、一种基于视觉密码学和可信计算的无密钥依赖的医学图像安全隐私保护框架A Privacy Protection Framework for Medical Image Securi…...

计算机基础小结

目录 ❤ 计算机基础编程 什么是编程语言? 什么是编程? 为什么要学习编程? ❤ 计算机组成原理 控制器 运算器 储存器 内存(主存) 外存 输入设备 输出设备 适配器 总线 机械硬盘 固态硬盘 ❤ 计算机操作系统 什么是操作系统? 什么是文件? 什么是应…...

Linux服务器还有漏洞?建议使用 OpenVAS 日常检查!

几乎每天都会有新的系统漏洞产生,系统管理员经常忙于管理服务器,有时候会忽略一些很明显的安全问题。扫描 Linux 服务器以查找安全问题并不是很简单的事情,所以有时候需要借助于一些专门的工具。 OpenVAS 就是这样一种开源工具,它…...

【Redis】P1 Redis - NoSQL

Redis - NoSQLSQL 与 NoSQL差别一:结构化 与 非结构化差别二:关联性 与 非关联性差别三:规范化查询语句 与 非规范化差别四:事务 与 无事务差别五:磁盘存储 与 内存存储RedisRedis 的安装当前数据库存储主要分为 关系型…...

Angular学习之ControlValueAccessor接口详解

ControlValueAccessor 是什么?为什么需要使用 ?下面本篇文章就来带大家了解Angular中的ControlValueAccessor组件接口,希望对大家有所帮助! ControlValueAccessor 是什么? 简单来说ControlValueAccessor是一个接口&am…...

【GORM】高级查询方案

【GORM】高级查询方案1.Struct & Map查询为空的情况2.FirstOrInit3.FirstOrCreate4.高级查询1.Struct & Map查询为空的情况 当通过结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果你的字段值为0,‘’,false…...

MFC 简单使用事件

功能三个按钮,一个静态框,默认值是0,增加减少按钮和退出按钮.增加减少按钮显示在静态框中.退出按钮退出软件.实验事件思路新建三个事件,add事件sub事件quit事件,一个按钮触发一个事件,静态框新建一个线程接受事件做出对应的改变.UI添加的代码就不具体说,具体说下事件的代码,这才…...

华为OD机试题 - 端口合并(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:端口合并题目输入输出示例一输入输出说明示例二输入输出说明示例…...

ECharts数据可视化--常用图表类型

目录 一.柱状图 1.基本柱状图 1.1最简单的柱状图 ​编辑 1.2多系列柱状图 1.3柱状图的样式 (1)柱条样式 (2)柱条的宽度和高度 (3)柱条间距 (4)为柱条添加背景颜色 ​编辑 2.堆…...

Flutter面试题解析-GridView详解与应用

一、前言Flutter 作为时下最流行的技术之一,凭借其出色的性能以及抹平多端的差异优势,早已引起大批技术爱好者的关注,甚至一些 闲鱼 , 美团 , 腾讯 等大公司均已投入生产使用。虽然目前其生态还没有完全成熟&#xff0…...

最全的论文写作技巧(建议收藏)

近10年来,笔者有幸多次参与教学论文的评审工作,在此,特将教学论文写作的步骤及相关问题整理汇总如下: 一、选定论题 (一)论题在文中的地位与作用 严格地讲,论文写作是从选定论题开始的。选题…...

面向对象设计模式:设计模式分类(创建型、行为型、结构型)

1. 创建型设计模式 单例模式:https://blog.csdn.net/qq_44992559/article/details/129348686工厂模式:https://blog.csdn.net/qq_44992559/article/details/115222311抽象工厂模式:https://blog.csdn.net/qq_44992559/article/details/12934…...

MySQL数据库迁移

考试系统的数据库一直是在我自己的服务器上面的, 但是最近,自己的服务器马上要过期了,里面的MySQL数据需要迁移出来,放在另外一个服务器上面。百度了几篇教程,也没研究太多,选了一种比较简单的方式进行迁移…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

2025季度云服务器排行榜

在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

Java编程之桥接模式

定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...