创建型模式 - 原型模式

news2024/10/7 14:22:50

概述

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

结构

原型模式包含如下角色:

  • 抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。

  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。

  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

接口类图如下:

 

实现

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

浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。

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

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

Realizetype(具体的原型类):

public class Realizetype implements Cloneable {

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

    @Override
    protected Realizetype clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");
        return (Realizetype) super.clone();
    }
}

PrototypeTest(测试访问类):

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));
    }
}

案例

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

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

类图如下:

代码如下:  

//奖状类
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();
    }
}

使用场景

  • 对象的创建非常复杂,可以使用原型模式快捷的创建对象。

  • 性能和安全要求比较高。

扩展(深克隆)

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

//奖状类
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)中的引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流。代码如下:

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

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

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

相关文章

如何用3D格式转换工具HOOPS Exchange读取颜色和材料信息?

作为应用程序开发人员,非常希望导入部件的图形表示与它们在创作软件中的外观尽可能接近。外观可以在每个B-Rep面的基础上指定,而且,通过装配层次结构的特定路径可以在视觉外观上赋予父/子覆盖。HOOPS ExchangeHOOPS Exchange可捕获有关来自各…

创建型模式 - 建造者模式

概述 将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况。 由于实现了构建和装配的解耦。…

虾皮、Lazada爆款打造计划,自养号测评补单技术成重要的运营手段【无标题】

在如今的电商平台中,虾皮和lazada是东南亚地区主要的电商平台,平台广告是它的主要利润来源之一。然而,随着大量卖家涌入东南亚市场,商家之间的竞争也日益激烈,高额的广告投入并没有带来预期的效果。为了提高产品在平台…

【26】SCI易中期刊推荐——计算机人工智能(中科院4区)

💖💖>>>加勒比海带,QQ2479200884<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉…

【视频+文字讲解】C++那些事之彻底搞懂STL HashTable

C那些事之彻底搞懂STL HashTable C那些事之彻底搞懂STL HashTable1.常用容器 1.1 接口层2.HashTable原理 2.1 _Hash_node结构2.2 hashtable实现2.3 如何确定桶&#xff1f;2.4 如何确定在桶中的位置&#xff1f;3.Rehash 3.1 计算新桶大小3.2 判断是否需要rehash3.3 rehash 最近…

Github实时数据分析与可视化训练营火热开启!免费领取5000元云上资源

此次训练营内容基于GitHub Archive公开数据集&#xff0c;通过DataWorks将GitHub中的项目、行为等20多种事件类型数据实时采集至Hologres进行分析&#xff0c;同时使用DataV内置模板&#xff0c;快速搭建实时可视化数据大屏&#xff0c;从开发者、项目、编程语言等多个维度了解…

vscode 使用ssh进行远程开发 (remote-ssh)

介绍 visual studio code remote - ssh 可以通过ssh连接远程主机、虚拟机&#xff0c;打开远程文件夹&#xff0c;并利用vscode 的插件优势进行远程开发、调试等。 步骤 一、配置环境 因为remote-ssh 的ssh连接是基于openssh实现的&#xff0c;以及后续我们需要使用生成ss…

手把手教你搭建SpringCloud项目(七)集成Consul服务注册中心

一、了解Consul 这篇文章学习另外一个服务注册中心Consul&#xff0c;那什么是Consul&#xff1f; Consul是一个服务网格&#xff08;微服务间的 TCP/IP&#xff0c;负责服务之间的网络调用、限流、熔断和监控&#xff09;解决方案&#xff0c;它是一个一个分布式的&#xff…

[PCIE体系结构导读]PCIE总结(二)

PMCR&#xff08;Power Management Capabilities Register&#xff09;和PMCSR&#xff08;Power Management Control and Status Register) PMCR寄存器由16位组成&#xff0c;其中所有位和字段都是只读的。该寄存器的主要木得是记录当前PCIe设备的物理属性&#xff0c;系统软件…

vue2的 element 表格单元格合并

<template><div><el-table show-summary :summary-method"getSummaries" :span-method"objectSpanMethod" :data"tableData" row-key"id" ref"tableDom" border><el-table-column label"序号&quo…

10-2. 数组 Array 的实例方法

本文并没有写出数组的全部使用方法&#xff0c;想看全的可以看一下这个 Array - JavaScript | MDN 目录 1 常用内置方法 1.1 合并数组 concat() 1.2 复制元素覆盖到指定位置 copyWithin() 1.3 返回其他变量的数组形式 Array.from() 1.3.1 基本使用 1.3.2 将伪数组…

Hive Metastore、Hive server和Hive thrift服务

Hive Metastore Hive Metastore是Hive的核心元数据管理服务,它提供了元数据的持久化存储和访问控制的能力,使得 Hive 成为一个强大的数据仓库和分析平台,适用于处理大数据和进行复杂的数据查询与分析任务。 Apache Hive是一个建立在 Apache Hadoop 上的数据仓库和分析工具…

java多线程之FutureTask、Future、CompletableFuture

前面已经在多线程创建的时候有提到Future和FutureTask的简单用法&#xff0c;这里详细介绍下FutureTask以及CompletableFuture 一、FutureTask 1、FutureTask简介 FutureTask除了实现Future接口外&#xff0c;还实现了Runnable接口。因此&#xff0c;FutureTask可以交给 Exe…

回溯法实现N皇后问题

题1&#xff1a;&#xff08;需打印矩阵&#xff09; 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#…

命名空间,缺省参数与函数重载

目录 一&#xff0c;命名空间 1.何为命名空间 2.命名空间的使用 ​编辑 4.::作用域限定符 3.命名空间的展开 全局展开&#xff1a; 局部展开&#xff1a; 4.嵌套命名空间 二&#xff0c;缺省参数与函数重载 1.什么是缺省参数 2.什么是函数重载 3.两者的冲突 一&…

内部数据泄露:保护数据安全的挑战与解决方案

导语&#xff1a; 在当今数字化时代&#xff0c;数据是企业的核心资产之一。然而&#xff0c;随着科技的快速发展和信息的日益增长&#xff0c;数据安全问题也日益突出。其中&#xff0c;内部数据泄露成为企业所面临的重大挑战之一。本文将探讨内部数据泄露的危害&#xff0c;…

简直太高效了!一篇文章帮你快速了解企业如何实现无纸化办公

随着科技的发展和信息技术的普及&#xff0c;无纸化办公已经成为了现代企业的一个趋势。无纸化办公即指在企业日常工作中&#xff0c;尽量减少或不使用纸张作为工作载体&#xff0c;通过电子邮件、电子文档、电子表格等工具实现信息的传递和共享。无纸化办公不仅有利于环保&…

路由器隔绝广播,为什么还要VLAN?

路由器能隔绝广播&#xff0c;那要VLAN有什么用&#xff0c;既配置了VLAN又划分在不同的网段是不是有些多余了&#xff1f; 题主的意思是不要VLAN&#xff0c;可以吗&#xff1f; 当然可以。可以是可以&#xff0c;但是每台主机都能接收到路由器同一个接口&#xff08;三层/路…

如何正确有效的学习java前端(合集)

大量阅读 我是一个劲头十足的读者。所以&#xff0c;我的第一个关于学习JavaScript的技巧就是关于阅读&#xff0c;这绝不是巧合。书籍和其他的资源(如文章)可以在很大程度上帮助你学习JavaScript。通过实践学习&#xff0c;书籍是我学习新学科最喜欢的方式。在学习JavaScript的…

如何快速新建Linux虚拟机,安装linux系统步骤

1、安装好VMware workstation 软件&#xff1a;vmware workstation centos 7 2、点击创建新的虚拟机 3、选择安装操作系统&#xff0c;&#xff08;我这里使用centos-7 最简安装包&#xff0c;这种系统开销比较小&#xff0c;对机器性能要求不高&#xff09; 硬盘根据实际…