创建者模式—原型模式(深克隆和浅克隆的区别)

news2024/12/25 20:03:59

目录

1.原型模式

1.1概念

1.2结构

1.3实现

1.4案例

1.5深克隆(扩展)

2.浅克隆和深克隆

2.1克隆的特点

2.2浅克隆和深克隆的区别


1.原型模式

1.1概念

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

1.2结构

原型模式包含如下角色:

  • 抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。
  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

接口类图如下:

 

1.3实现

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

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

public class Realizetype implements Cloneable {

    public Realizetype() {
        System.out.println("具体的原型对象创建完成!");
    }

    @Override
    protected Realizetype clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");
        return (Realizetype) super.clone();
    }
}
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));
    }
}

1.4案例

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

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

 

//奖状类
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学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }

    @Override
    public 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();
    }
}

因为name是String类型的所以会复制一份并不会显示出浅克隆的弊端

1.5深克隆(扩展)

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

此时如果按照上述的方法克隆,show方法显示出来的就会都是李四

//奖状类
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学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }

    @Override
    public 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)中的引用类型的属性进行引用的复制。

因为STudent类属于自定义类浅克隆并不会复制,只会引用原对象,后面克隆的对象姓名改变后原对象也会改变,这样就暴露出了浅克隆的弊端这种情况需要使用深克隆,而进行深克隆需要使用对象流。

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异常。

2.浅克隆和深克隆

2.1克隆的特点

1、被克隆的对象的类应实现 Cloneable 接口,并重写 clone() 方法
2、浅克隆中8种基本数据类型和String类型会被克隆,而除此之外的类型数据不会被克隆,例如自定义Student类,因此当通过新对象对这些属性进行修改时,原对象的属性也会同时改变。而深克隆则已经对这些属性重新分配内存,所以当通过新对象对这些属性进行修改时,原对象的属性不会改变。

2.2浅克隆和深克隆的区别

1、浅克隆:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,浅克隆并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性)
2、深克隆:深克隆是在浅克隆的基础上,递归地克隆除8种基本数据类型和String类型外的属性(即为这些属性重新分配内存而非引用原来对象中的属性)
 

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

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

相关文章

【分布式任务调度】XXL-JOB快速搭建教程

XXL-JOB1. XXL-JOB简介2. XXL-JOB搭建2.1 准备工作2.1.1 下载源码2.1.2 数据库准备 数据库脚本在doc路径下,将其执行之后可以创建一个数据库,如图3所示:2.2 搭建调度中心2.3 搭建“执行器”3. 测试3.1 新增执行器3.2 新增任务3.3 启动任务测试…

【工作笔记0036】C#中Decimal小数取整容易犯错的坑

这两天排查一个bug,数据库中同样的计算公式 和 C#代码中一毛一样的计算公式,最后结果为 Decimal 类型的小数,需求保留两位小数。但是结果是数据库中 和 代码中的结果总是对不上。整理并简化了一下项目中代码计算公式:decimal a 3…

vitest第一章(初始vitest)

从三个角度分析vitest 他能做什么? 为什么要使用他? 使用它的优势是什么? vitest官网cn.vitest.dev/ 1.vitest能做什么 从官网介绍说这是一个单元测试框架,大家听到有测试两个字觉得这个是测试同学写的东西,其实这个…

低版本浏览器(webview)空数据音频文件异常报错

问题背景 监控出现大量静态资源加载异常报警,ios和安卓各系统版本都有(排查了一段时间,发现是QA同学在全量测试,无语凝噎)QA测试反馈,报告页在收音失败的情况稳定复现播放音频失败(确实有问题&…

Qos实验配置-CBQ方式

目录 对报文进行重标记 对数据报文进行流量监管-接口入方向 将报文加入相应队列 为语音业务配置丢弃策略 配置流量整形-接口出方向 QoS理论讲解_静下心来敲木鱼的博客-CSDN博客_qos 优先级映射https://blog.csdn.net/m0_49864110/article/details/127414766?ops_request_…

MATLAB 绘制数据图

✅作者简介:人工智能专业本科在读,喜欢计算机与编程,写博客记录自己的学习历程。 🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心&…

python中的socket套接字基础 (客户端服务器信息交互)

文章目录1 socket概述2 socket使用2.1 socket常用函数2.2 简单实现 客户端与服务器 信息交互2.3 多线程实现服务器和客户端信息交互1 socket概述 Python中,我们利用Socket套接字来实现网络通信,可以说套接字是实现网络编程进行数据传输的一种技术手段。S…

UNIX环境高级编程_文件IO_共享文件操作

这篇笔记记录下,多进程(包括父子进程)操作同一个文件,或者同一个文件被同一个进程多次打开时的情况,总是傻傻分不清,必须记录一下了。 1 文件IO_共享文件 分下面四种情况记录。 情况1:同一进程多次open同一个文件 …

SAP MESSAGE :000 消息提示「BUG」

SAP MESSAGE :000 消息提示 错误消息 问题分析 前言&#xff1a;这个问题 DEBUG 模式没有抓到&#xff0c;所以才有了下文&#xff1a; 这是迁移程序时会出现的问题&#xff0c;参见下面的图片&#xff1a; 在迁移前&#xff0c;MATNR 转码 FUNC 就没有规范书写 sy-subrc <…

第十三章 常用类(包装类和String 相关类)

一、包装类 1. 包装类的分类 &#xff08;1&#xff09;针对八种基本数据类型相应的引用类型—包装类 &#xff08;2&#xff09;有了类的特点&#xff0c;就可以调用类中的方法。 2. 包装类和基本数据的转换 &#xff08;1&#xff09;jdk5 前的手动装箱和拆箱方式 public cl…

好友靠JVM成功进入阿里,阿里P8力荐的JVM笔记到底有什么魔力?

大家都是有经验的Java开发人员&#xff0c;想想为何要学习JVM? [面试?调优?装逼? ] 不管出于何种原因&#xff0c;总之你得先学好。那怎么学好呢? 每个人对于JVM的了解可能不一样&#xff0c;这就要考虑到怎么切入 既然大家都学习过Java&#xff0c;那不妨就从Java开始…

数据分析思维(四)|分类/矩阵思维

分类与矩阵思维 1、概念 在进行数据分析工作时&#xff0c;我们往往会涉及到多个核心指标&#xff0c;而对于不同数值核心指标的结合又会产生多种不同的结果&#xff0c;我们将相似结果的内容放到一起进行统一决策就会大大节省数据分析的时间&#xff0c;这种思想我们称之为分…

[python入门㊲] - python的继承

目录 ❤ 什么是继承 ❤ 派生和继承 ❤ 单继承 ❤ 多继承 ❤ MRO[方法搜索顺序](多继承顺序) ❤ 新式类和旧式&#xff08;经典&#xff09;类 ❤ 什么是继承 通过继承基类来得到基类的功能 所以我们把被继承的类称作父类或基类&#xff0c;继承者被称作子类 可…

注册外贸公司需要注意的问题

关于注册海外公司需要注意事项&#xff0c;米贸搜以美国为例&#xff0c;整理以下信息&#xff0c;希望可以帮助到你一、注册美国公司注意事项&#xff1a;1、拟定要注册的美国公司名称三个&#xff08;英文&#xff09;&#xff0c;核名如无重复则可使用&#xff1b;2、美国公…

matlab机电耦合系统相位分岔图

1、内容简介略638-可以交流、咨询、答疑2、内容说明略3、仿真分析clcclose allclear%% parameterglobal CC 48;tspan [0 5]; % 仿真时间x0 [0.1 0.1 0.1 0.1]; % 变量初始值[T,X] ode45(model_diff, tspan, x0); % 调用求解器X3_dot [0;diff(X(:,3))./diff(T)]; % 求解x3的…

【已解决】SpringCloudConfig客户端启动无法读取到配置参数

自己部署了一个Spring Cloud微服务项目&#xff0c;实践Spring Cloud Config分布式配置组件&#xff0c;按照Spring Cloud Config 资料Config&#xff1a;Spring Cloud分布式配置组件 先后创建了Eureka注册中心服务、 Spring Cloud Config Server服务、 Spring Cloud Config Cl…

极客星球 | Elasticsearch入门与实战技术分享

为持续夯实MobTech袤博科技的数智技术创新能力和技术布道能力&#xff0c;本期极客星球邀请了MobTech企业服务研发部工程师勤佳&#xff0c;从Elasticsearch集群安装、DSL语句讲解、深度分页、IK分词器、滚动索引等方面进行了阐述和分享。 一、集群环境安装 elasticsearch 是…

节后转岗“浪潮”来了!瞅准“趋势向上”的行业!

“跨行跨岗人员&#xff0c;怎么能顺利转行&#xff1f;”的话题一直存在&#xff01;成功人士给出一条转岗转行的原则&#xff1a;迁移到技能相近但趋势向上的岗位。那么&#xff0c;什么叫“技能相近”和“趋势向上”呢&#xff1f;让我们来看看。趋势向上除了技能相近&#…

现阶段元宇宙经常偏离原有的发展轨道,使其失去该有的功能和意义

人们总是会自然地陷入到约定俗成的俗套之中。对于元宇宙&#xff0c;同样未能免俗。即使是那些处于头部的玩家&#xff0c;亦不例外。比如&#xff0c;扎克伯格就仅仅只是将元宇宙看成了一个将脸书带离泥潭的工具&#xff0c;一味地迎合资本&#xff0c;而最终忽略了元宇宙最本…

日常避坑--input输入框type=number仍可以输入“e“,“.“等符号

问题发现在使用ElementUI的input框时候&#xff0c;我们有时候需要只让用户输入数字类型。这个时候你可能就会想到<input type"number">,思路没错&#xff0c;但是踩着坑啦。我定义了一个number类型的input框但是&#xff0c;输入框仍旧可以输入"e",…