设计模式之原型模式(Prototype)

原型模式

如果已经有一个对象了,你想创建一个对象,而且对象里面的属性和已经存在的对象的属性差不多,就可以使用clone方法
克隆一个出来
在这里插入图片描述

实现原型模式需要实现标记型接口Cloneable -->标记型接口 : 里面没有需要实现的方法(空接口)
一般会重写clone方法 --> 如果只是重新clone方法,而没有实现Cloneable接口,调用时会报异常
一般用于一个对象的属性以及确定,需要产生很多相同或大部分属性相同的对象的时候
需要区分深克隆和浅克隆

java自带,Object类里面有个Object.clone()。也称为克隆模式
clone方法是protected native方法 C++实现 只能子类调用

浅克隆:
Object的clone,是在内存里面重新创建一个对象,copy过来原来对象的属性,如果是基本数据类型,拷贝的是值过去,
如果是引用数据类型,拷贝的是对象的内存地址,指向的是同一个对象,互相有影响
有没有方法把引用的对象也拷贝一份呢? --> 深克隆

/*** 浅克隆*/public class Test {public static void main(String[] args) throws Exception {Person p1 = new Person();// 克隆Person p2 = (Person)p1.clone();// 基本数据类型,值直接copy过来System.out.println(p2.age + " " + p2.score);System.out.println(p2.loc);// 引用数据类型,copy的是内存地址,指向的是同一个对象,所以相等System.out.println(p1.loc == p2.loc); // true// 如果p1对象的loc改变了,p2的loc也会改变p1.loc.street = "sh";System.out.println(p2.loc); // sh}
}// 实现Cloneable接口
class Person implements Cloneable {int age = 8;int score = 100;Location loc = new Location("bj", 22);// 实现clone方法@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}class Location {String street;int roomNo;@Overridepublic String toString() {return "Location{" +"street='" + street + '\'' +", roomNo=" + roomNo +'}';}public Location(String street, int roomNo) {this.street = street;this.roomNo = roomNo;}
}

深克隆:
引用的对象Location也实现Cloneable接口以及clone方法,在clone Person对象的时候将原来对象的loc也clone一份出来,
然后新clone出来 的对象的loc引用指向clone处理的loc

/*** 深克隆的处理*/
public class Test {public static void main(String[] args) throws Exception {Person p1 = new Person();Person p2 = (Person)p1.clone();System.out.println(p2.age + " " + p2.score); // 8 100System.out.println(p2.loc);// 不是同一个对象了System.out.println(p1.loc == p2.loc); // falsep1.loc.street = "sh";// 改变p1的loc不好影响p2System.out.println(p2.loc); // bj}
}class Person implements Cloneable {int age = 8;int score = 100;Location loc = new Location("bj", 22);@Overridepublic Object clone() throws CloneNotSupportedException {// clone一份新的对象出来Person p = (Person)super.clone();// 将原来的loc,也clone一份出来,新对象的loc指针指向clone处理的loc对象p.loc = (Location)loc.clone();return p;}
}
// 被引用的对象实现Cloneable接口以及clone方法
class Location implements Cloneable {String street;int roomNo;@Overridepublic String toString() {return "Location{" +"street='" + street + '\'' +", roomNo=" + roomNo +'}';}public Location(String street, int roomNo) {this.street = street;this.roomNo = roomNo;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}

引用数据类型,在深克隆的时候,是需要被克隆一份的,上面的String也是引用数据类型,clone的时候也需要将它克隆一份吗?
不需要。
String类型放在了常量池里面,比如说第一个Person对象里面的String指向的是常量池里面的"bj",clone出来的对象也是指向的常量池里面的"bj",
如果第一个Person对象里面的String变成了"sh",是不会影响第二个对象的,因为只是第一个对象里面的String指向了常量池里面的"sh",被克隆出来
的对象还是指向的"bj"。

/*** String需要进一步深克隆吗?*/
public class Test {public static void main(String[] args) throws Exception {Person p1 = new Person();Person p2 = (Person)p1.clone();System.out.println(p2.age + " " + p2.score);System.out.println(p2.loc);System.out.println(p1.loc == p2.loc); // falsep1.loc.street = "sh";System.out.println(p2.loc);p1.loc.street.replace("sh", "sz");// 改变p1里面的string,不好影响p2System.out.println(p2.loc.street); // bj}
}class Person implements Cloneable {int age = 8;int score = 100;Location loc = new Location("bj", 22);@Overridepublic Object clone() throws CloneNotSupportedException {Person p = (Person)super.clone();p.loc = (Location)loc.clone();return p;}
}class Location implements Cloneable {String street;int roomNo;@Overridepublic String toString() {return "Location{" +"street='" + street + '\'' +", roomNo=" + roomNo +'}';}public Location(String street, int roomNo) {this.street = street;this.roomNo = roomNo;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}

下面的例子中,String用的是StringBuilder,Person 1和Person 2里面的String都是指向的同一个StringBuilder,所以
当Person 1的String改变之后,Person 2的String也会改变。
怎么解决? --> 深克隆的时候,也需要把StringBuilder克隆一份

/*** String需要进一步深克隆吗?*/
public class Test {public static void main(String[] args) throws Exception {Person p1 = new Person();Person p2 = (Person)p1.clone();// loc 经过clone之后指向的不是同一个对象System.out.println("p1.loc == p2.loc? " + (p1.loc == p2.loc)); // false// p1和p2里面的String指向的是同一个StringBuilder,所以当p1里面的String改变的时候,// p2的也会改变p1.loc.street.reverse();System.out.println(p2.loc.street); // jb}
}class Person implements Cloneable {int age = 8;int score = 100;Location loc = new Location(new StringBuilder("bj"), 22);@Overridepublic Object clone() throws CloneNotSupportedException {Person p = (Person)super.clone();p.loc = (Location)loc.clone();return p;}
}class Location implements Cloneable {StringBuilder street;int roomNo;@Overridepublic String toString() {return "Location{" +"street='" + street + '\'' +", roomNo=" + roomNo +'}';}public Location(StringBuilder street, int roomNo) {this.street = street;this.roomNo = roomNo;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}

深克隆用的少,面试也问的少,了解就行

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

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

相关文章

数据运营基础:用户场景营销

一、概述 场景营销模型是顶层模型,是站在用户经营和用户场景角度来制定经营策略的模型。本质上,场景营销模型是在用户使用产品的每个细分场景中通过分析用户需求整合功能、实体和体验等为用户提供服务的模型。 二、场景的起源和特点 数据运营体系在发展…

RHCE第四次作业

题目 架设一台NFS服务器,并按照以下要求配置 1、开放/nfs/shared目录,供所有用户查询资料 2、开放/nfs/upload目录,为192.168.100.0/24网段主机可以上传目录, 并将所有用户及所属的组映射为nfs-upload,其UID和GID均为210 3、将…

ChatGPT重磅升级 奢侈品VERTU推出双模型AI手机

2023年11月7日,OpenAI举办了首届开发者大会,CEO Sam Altman(山姆奥尔特曼)展示了号称“史上最强”AI的GPT-4 Turbo。它支持长达约10万汉字的输入,具备前所未有的长文本处理能力,使更复杂的互动成为可能。此外,GPT-4 Turbo还引入了跨模态API支持,可以同时处理图片、视频和声音,从…

MySQL基础知识题目

1. 下面不属于数据库系统特点的是( ) A.数据冗余度高 B.数据具有完整性 C.数据共享性好 D.数据独立性高 正确答案:A 题解:数据库系统的特点包括数据独立性高、数据共享性好、数据冗余度低和数据具有完整性。 2. 不属于关系数…

Three.js——基于原生WebGL封装运行的三维引擎

文章目录 前言一、什么是WebGL?二、Three.js 特性 前言 Three.js中文官网 Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。既然Threejs是一款WebGL三维引擎,那么…

421. 数组中两个数的最大异或值/字典树【leetcode】

421. 数组中两个数的最大异或值 给你一个整数数组 nums &#xff0c;返回 nums[i] XOR nums[j] 的最大运算结果&#xff0c;其中 0 ≤ i ≤ j < n 。 示例 1&#xff1a; 输入&#xff1a;nums [3,10,5,25,2,8] 输出&#xff1a;28 解释&#xff1a;最大运算结果是 5 XOR…

基于YOLOv8的输电线路异物识别算法应用

基于 YOLOv8 的输电线路异物识别算法应用 输电线路作为电力系统的重要一环&#xff0c;保证其安全稳定运行是十分必要的。由于长期暴露于室外&#xff0c;线路所面临的不安全因素繁多&#xff0c;异物入侵便是其中之一。异物可能会引起线路短路甚至诱发火灾&#xff0c;因此要加…

react及相关面试问题汇总

目录 1、什么是React&#xff1f;它的特点是什么&#xff1f; 2、解释一下虚拟DOM(Virtual DOM)的概念以及它的工作原理。 3、什么是组件(Component)&#xff1f;如何定义一个React组件&#xff1f; 4、什么是JSX&#xff1f;它与HTML的区别是什么&#xff1f;如何在React中…

Unity中雾效的实现方法二

文章目录 前言一、声明雾效所需要的内置变体二、在 v2f 中声明顶点传入片段中的雾效插值器三、 在顶点着色器中计算雾效采样四、在片元着色器中进行雾效颜色混合在这里插入图片描述 五、最终效果 前言 Unity中雾效的实现方法二&#xff0c;使用 Unity 自带的方法实现&#xff…

如何将系统盘MBR转GPT?无损教程分享!

什么是MBR和GPT&#xff1f; MBR和GPT是磁盘的两种分区形式&#xff1a;MBR&#xff08;主引导记录&#xff09;和GPT&#xff08;GUID分区表&#xff09;。 新硬盘不能直接用来保存数据。使用前应将其初始化为MBR或GPT分区形式。但是&#xff0c;如果您在MBR时需…

torch.norm求范数

pytorch在数学计算上下足了功夫&#xff0c;在支持海量数学公式的同时还将速度优化到超过大部分用户DIY的水平。所以&#xff0c;pytorch中的每个常见的数学计算函数都需要我们有一定了解。 今天介绍的是torch.norm&#xff0c;一个pytorch用来求范数的函数。我们先看求范数的数…

基于FPGA的EMAC模块与FIFO模块:高速数据传输与存储

基于FPGA的EMAC模块与FIFO模块&#xff1a;高速数据传输与存储 在现代社会&#xff0c;高速数据传输和存储是信息技术领域的关键问题之一。而基于FPGA的EMAC模块与FIFO模块则成为了解决这些问题的重要途径。本文将介绍这两个模块的原理、实现方法以及如何在FPGA中应用它们。 …

关于我在配置zookeeper出现,启动成功,进程存在,但是查看状态却没有出现Mode:xxxxx的问题和我的解决方案

在我输入:zkServer.sh status 之后出现报错码. 报错码&#xff1a; ZooKeeper JMX enabled by default Using config: /opt/software/zookeeper/bin/../conf/zoo.cfgClient port found: 2181. Client address: localhost. Error contacting service. It is probably not runni…

基于SpringBoot的SSMP整合案例(开启日志与分页查询条件查询功能实现)

开启事务 导入Mybatis-Plus框架后&#xff0c;我们可以使用Mybatis-Plus自带的事务&#xff0c;只需要在配置文件中配置即可 使用配置方式开启日志&#xff0c;设置日志输出方式为标准输出mybatis-plus:global-config:db-config:table-prefix: tb_id-type: autoconfiguration:…

【自动化测试】Pytest框架 —— 跳过测试和失败重试

1、Pytest跳过测试用例 自动化测试执行过程中&#xff0c;我们常常出现这种情况&#xff1a;因为功能阻塞&#xff0c;未实现或者环境有问题等等原因&#xff0c;一些用例执行不了&#xff0c; 如果我们注释掉或删除掉这些测试用例&#xff0c;后面可能还要进行恢复操作&#…

ObRegisterCallbacks()返回0xC0000022(拒绝访问)解决办法

在开发测试环境下&#xff0c;没有打签名的驱动调用ObRegisterCallbacks会返回0xC0000022&#xff08;拒绝访问&#xff09;的错误码。这是由于该函数内部会进行驱动的签名校验。 具体位置在 因此可以用以下代码绕过该检查 // 以下代码放在DriverEntry中 ULONG_PTR pDrvSectio…

【手动创建UIWindow Objective-C语言】

一、上节课,我们讲了控制器View的懒加载: 1.什么时候会调用这个懒加载呢,用我们直接,控制器self.view self.view的时候: 什么时候,调用它这个self.view, 就要去加载控制器的view, self.view 加载控制器的view 我们给大家演示过了,这个大家已经清楚了,我们给大家说…

vb.net圣经带快捷键,用原装的数据库

Imports System.Data.SqlServerCe Imports System.Text.RegularExpressions Imports System.Data.OleDbPublic Class Form1Dim jiuyue As String() {"创", "出", "利", "民", "申", "书", "士", "…

vue3使用粒子特效

安装 //使用npm安装 npm install particles.vue3 --save//使用yarn安装 yarn add particles.vue3 --save//必须得装 npm i tsparticles 使用 main.js import Particles from particles.vue3 const app createApp(App) app.use(Particles)//使用粒子特效 页面使用 <sc…

VScode配置C/C++环境

文章目录 一、下载MinGW二、配置环境变量三、VScode配置四、验证 一、下载MinGW MinGW官网 划到最下面找 二、配置环境变量 解压后放到自己想放的目录下 右键 此电脑–>属性–>高级系统设置—>环境变量–> 在cmd命令行检测&#xff0c;出现如下界面&#xff1a;…