【Java 设计模式】创建者模式 之原型模式

news2025/1/24 22:31:48

原型模式

  • §1 定义
  • §2 角色
  • §3 三好学生案例
    • §3.1 浅克隆实现
      • §3.1.1 浅克隆定义
      • §3.1.2 类图
      • §3.1.3 实现
    • §3.2 深克隆实现
      • §3.2.1 深克隆定义
      • §3.2.2 实现

§1 定义

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

§2 角色

  • 抽象原型类:定义具体原型类需要实现的 clone 方法,对于 Java 来说,具体原型类直接实现 Cloneable 接口重写 clone 方法即可,无需再重新定义抽象原型类。
  • 具体原型类:实现抽象原型类的 clone 方法。
  • 访问类:使用具体原型类中的 clone 方法复制新对象。

§3 三好学生案例

  • 班级里有多名同学获得了三好学生的奖状,除了奖状上的获奖人姓名不一样外,其他都是一样的,使用原型模式复制出多个三好学生奖状,然后修改奖状上的名字。

§3.1 浅克隆实现

§3.1.1 浅克隆定义

  • 创建一个新的对象,新对象的属性和原型对象的完全相同,对于非基本类型的属性,仍然指向原型对象所指向的对象的内存地址

§3.1.2 类图

在这里插入图片描述

§3.1.3 实现

// 具体原型类: 奖状
public class Citation implements Cloneable {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void show() {
        System.out.println("三好学生:" + name);
    }
    @Override
    protected 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();
    }
}
/* 输出结果:
三好学生:张三
三好学生:李四
*/
  • 浅克隆模式看似一切正常,若我们把 Citation 的 name 属性改为 Student 自定义对象,再来看看会发生什么?
// 学生类
public class Student {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

// 具体原型类: 奖状
public class Citation implements Cloneable {
    private Student student;
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
    public void show() {
        System.out.println("三好学生:" + student.getName());
    }
    @Override
    protected Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }
}

// 访问类
public class CitationTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation c1 = new Citation();
        Student student1 = new Student();
        student1.setName("张三");
        c1.setStudent(student1);
        Citation c2 = c1.clone();
        Student student2 = c2.getStudent();
        student2.setName("李四");
        System.out.println("student1和student2是同一个对象吗?" + (student1 == student2));
        c1.show();
        c2.show();
    }
}
/* 输出结果:
student1和student2是同一个对象吗?true
三好学生:李四
三好学生:李四
*/
  • 测试结果可以看出,两个 student 对象是同一个对象,当修改克隆后的学生名字时,原型对象的名字也被修改了,这是浅克隆方式的弊端。可以使用深克隆方式解决。

§3.2 深克隆实现

§3.2.1 深克隆定义

  • 创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象的地址。

§3.2.2 实现

// 学生类
public class Student implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

// 具体原型类: 奖状
public class Citation implements Cloneable, Serializable {
    private Student student;
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
    public void show() {
        System.out.println("三好学生:" + student.getName());
    }
    @Override
    protected Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }
}

// 访问类
public class CitationTest {
    public static void main(String[] args) throws Exception {
        Citation c1 = new Citation();
        Student student1 = new Student();
        student1.setName("张三");
        c1.setStudent(student1);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\study\\a.txt"));
        oos.writeObject(c1);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\study\\a.txt"));
        Citation c2 = (Citation) ois.readObject();
        ois.close();
        Student student2 = c2.getStudent();
        student2.setName("李四");
        System.out.println("student1和student2是同一个对象吗?" + (student1 == student2));
        c1.show();
        c2.show();
    }
}
/* 输出结果:
student1和student2是同一个对象吗?false
三好学生:张三
三好学生:李四
*/
  • 使用序列化和反序列化的方式实现深克隆,解决浅克隆的弊端。

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

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

相关文章

Chrome的使用技巧

1. 请求重发 F12 -> Network -> Replay XHR 2. 修改请求参数后重发 F12 -> Network -> Copy -> Copy as fetch 然后在 Console 控制台 ctrl + v ,而后就可以对请求的参数进行编辑,回车就会重更新请求 再在 Network 就可以看到这个请求了 3. 复制对象 (…

echarts入门到实战

官网地址:Apache ECharts 前言 我们应该经常看到或听到”数据可视化“这个词,他其实就是将数据通过各种图表更加直观的展现变化趋势,对比,峰值等等。数据可视化也是未来的趋势。 作为前端程序员,数据可视化也是我们必…

多任务全景感知YOLOPv2:目标检测、freespace、车道线

今年年初出了一片《端到端的多任务感知网络HybridNet,性能优于YOLOP》,论文 HybridNets: End2End Perception Network,代码已开源,在目标检测、车道线、freespace的多任务感知任务上性能优于YOLOP,取得了新SOTA。视频效…

大厂Java面试必备面试题:基础语法-数据类型-编码-注释-运算符-关键字-流程控制语句

基础语法 数据类型 Java有哪些数据类型 定义:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类 型,在内存中分配了不同 大小的内存空间。 分类: 基本数据类型 Java源代码---->编译器---->jvm可执行的Java字…

如果Controller里有私有的方法,能成功访问吗?

背景 写代码的时候,复制粘贴的时候,没注意到方法的属性,就导致了Controller里有了一个私有的方法,然后访问这个接口的时候就报了空指针异常,找了好久才找到是这个原因。 来看一个例子 Service public class MyServi…

Netty面试经典问题

目录 Netty是怎么实现高性能设计的? 简单介绍一下对于Netty的了解 Netty的高性能表现在哪些方面 介绍一下Java中的几种IO模型 一个通俗例子读懂BIO、NIO、AIO BIO与NIO的区别 Netty的线程模型 什么是零拷贝 Netty中的模块组件: Netty 中有哪种…

Linux rpm方式安装 MYSQL8.0

1.卸载原有的mysql 数据库 1)查找安装的mysql软件包和依赖包: rpm -pa | grep mysql 显示结果: mysql80-community-release-el7-1.noarch mysql-community-server-8.0.11-1.el7.x86_64 mysql-community-common-8.0.11-1.el7.x86_64 mysql…

ReLU,Sigmoid,Tanh,softmax【基础知识总结】

一、ReLU(Rectified Linear Activation Function)1、优点2、缺点补充二、Sigmoid1、优点2、缺点三、Tanh四、Sigmoid 和 Tanh 激活函数的局限性五、softmax(待补充)激活函数的引入是为了增加神经网络模型的非线性,没有…

【机器学习入门项目10例】(九):聚类算法用于降维,KMeans的矢量量化应用(图片压缩)

🌠 『精品学习专栏导航帖』 🐳最适合入门的100个深度学习实战项目🐳🐙【PyTorch深度学习项目实战100例目录】项目详解 + 数据集 + 完整源码🐙🐶【机器学习入门项目10例目录】项目详解 + 数据集 + 完整源码🐶🦜【机器学习项目实战10例目录】项目详解 + 数据集 +

万字长文!对比分析了多款存储方案,KeeWiDB最终选择自己来

大数据时代,无人不知Google的“三驾马车”。“三驾马车”指的是Google发布的三篇论文,介绍了Google在大规模数据存储与计算方向的工程实践,奠定了业界大规模分布式存储系统的理论基础,如今市场上流行的几款国产数据库都有参考这三…

Fama-French三因子和五因子模型和Stata代码(内附原始数据)

一、Fama-French三因子模型数据和Stata代码(2000-2020年) 1、数据来源:原始数据在分享文件中 2、时间跨度:2000-2020年 3、区域范围:全国 5、原始数据: 4、指标说明: 部分指标如下&#xff…

Linux虚拟机的克隆

文章目录🚏 Linux虚拟机的克隆🚀 克隆虚拟机🚬 1、虚拟机在未开启的状态下🚬 2、选择创建完整克隆🚬 3、选择虚拟机的名称和位置🚄 修改 克隆虚拟机的设置🚬 1、mac地址🚬 2、主机名…

RocketMQ安装部署

RocketMQ的物理部署结构图如下: Producer和Consumer对应的是我们的应用程序,多个NameServer实例组成集群,但相互独立,没有信息交换,所以对于NameServer来说部署两个或两个以上即可保证高可用,对于Broker来…

AWS Skill Builder - 练习 ACF 认证的第一站

AWS Skill Builder - 练习 ACF 认证的第一站 AWS Skill Builder https://explore.skillbuilder.aws/learn 是 AWS 针对要想要自学 AWS 云计算技术所提供的网站,里面提了很多自学的课程,今天要展示的是在学习完 AWS Academy Cloud Foundations 课程后&am…

车牌识别停车场智能管理系统

摘 要 本论文主要论述了如何使用JSP技术开发一个车牌识别停车场智能管理系统 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述车牌识别停车场智能管理系统的…

【Paraview教程】第一章安装与基础介绍

1 Paraview介绍 1.1基本介绍 ParaView是一个开源的,跨平台的数据处理和可视化程序。ParaView用户可以迅速的建立起可视化环境利用定量或者是定性的手段去分析数据。利用它的批量处理能力可以在三维空间内在工具栏和展示界面中进行交互操作,从而实现“数…

PDF中的某个图或表想几乎无损的插入ppt或者word里的方法

要使用ps打开pdf并另存为tiff或者,其他方法存储的tiff可能不如这种方法高清 0. 参考方法网址:PS导出符合投稿规范的图片 1. pdf可能很多页,一页内有很多图像文字,要先使用福昕阅读器(破解版本的)裁剪到想保留tiff的那张图或那个表…

四、nginx反向代理

一、反向代理 解释:nginx反向代理如正向代理原理类似,只是实现了不同的功能。客户端将请求发给服务端(代理服务器)后,服务端(代理服务器)并没有自己处理请求,而是交给被代理服务器&…

P4用软件实现和硬件实现的区别

摘要:我们目前看到从可配置性有限的固定功能网络设备向具有完全可编程处理流水线的网络设备的转变。这种发展的一个突出例子是P4,它提供了一种语言和参考架构模型来设计和编程网络设备。这个参考模型的核心元素是可编程匹配动作表,它定义了网…

[附源码]Python计算机毕业设计高校餐厅评价系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…