Java 23种设计模式(3.创建者模式-原型模式)

news2024/9/24 11:33:04

1.概述

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

2.结构

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

3.实现-类图

在这里插入图片描述
原型模式的克隆分为浅克隆深克隆
关于深浅克隆参考之前我写的文章

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

4. 代码

public class RealizeType implements Cloneable{
    public RealizeType(){
        System.out.println("it's original");
    }

    public RealizeType clone() throws CloneNotSupportedException{
        System.out.println("it's clone");
        return (RealizeType) super.clone();
    }
}

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        RealizeType realizeType = new RealizeType();//创建一个原型类对象
        RealizeType clone = realizeType.clone(); //调用Realizetype类中的clone方法进行对象的克隆
        System.out.println(realizeType==clone);//原型对象和克隆出来的是否是同一个对象
        System.out.println(realizeType.equals(clone));//原型对象和克隆出来的值是否相等
        System.out.println(realizeType.getClass()==realizeType.getClass());//原型对象和克隆出来的是否是同一个class
    }
}

运行结果:

it's original
it's clone
false
false
true

5. 案例

三好学生的奖状除了姓名不同,其他都相同

5.1 类图

5.2 代码

public class Citation implements Cloneable{
    String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Citation clone() throws CloneNotSupportedException{
        return (Citation) super.clone();
    }
    public void show(){
        System.out.println(getName() + "同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation original = new Citation();
        original.setName("aaaa");
        Citation clone = original.clone();//复制奖状
        clone.setName("bbbb");//将奖状的名字修改
        original.show();
        clone.show();
    }
}


5.3 运行结果

aaaa同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!
bbbb同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!

6. 使用场景

对象的创建非常复杂,可以使用原型模式快捷的创建对象。
性能和安全要求比较高。

7. 扩展(深克隆)

浅克隆

public class Student {
    private String name;
    private String address;

    public Student(String name,String address) {//构造方法
        this.name = name;
        this.address = address;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Citation implements Cloneable{
    private Student student;

    public void setStudent(Student student){
        this.student = student;
    }
    public Student getStudent(){
        return student;
    }
    public Citation clone() throws CloneNotSupportedException{
        return (Citation) super.clone();
    }
    public void show(){
        System.out.println(student.getName() + "同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation original = new Citation();
        Student student1 = new Student("aaaa","Shanghai");
        original.setStudent(student1);

        Citation clone = original.clone();//复制奖状
        clone.getStudent().setName("bbbb");//获取clone奖状并修改对象的名字  false

        System.out.println(original==clone);//原型对象和克隆出来的是否是同一个对象 false
        System.out.println(original.equals(clone));//原型对象和克隆出来的值是否相等 true
        System.out.println(original.getClass()==clone.getClass());//原型对象和克隆出来的是否是同一个class
        original.show();
        clone.show();
    }
}

运行结果:

false
false
true
bbbb同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!
bbbb同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!

在这里插入图片描述

深克隆

以上的代码让clone后的student的name改变,需要满足以下规则
深度克隆需要满足以下规则:

  1. 无需单独复制元数据。
  2. 原始类中的所有成员类都应支持克隆,并且上下文中原始类的克隆方法应在所有成员类上调用 super.clone() 。
  3. 如果某个成员类不支持克隆,那么在clone方法中,必须创建一个该成员类的新实例,并将其所有属性复制到新的成员类对象中。这个新的成员类对象将被设置在克隆对象中。
public class Student implements Cloneable {
    private String name;
    private String address;

    protected Object clone() throws CloneNotSupportedException{//添加了clone
        return super.clone();
    }
    public Student(String name,String address) {//构造方法
        this.name = name;
        this.address = address;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Citation implements Cloneable{
    private Student student;

    public void setStudent(Student student){
        this.student = student;
    }
    public Student getStudent(){
        return student;
    }

//    public Citation clone() throws CloneNotSupportedException{
//        return (Citation) super.clone();
//    }
//以上是浅拷贝的方法,以下是深拷贝的方法
    public Citation clone() throws CloneNotSupportedException{
        Citation cloned = (Citation) super.clone();
        cloned.setStudent((Student)cloned.getStudent().clone());//让对象也clone的范围内
        return cloned;
    }
    public void show(){
        System.out.println(student.getName() + "同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}

false
false
true
aaaa同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!
bbbb同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!

在这里插入图片描述

也可以使用对象流来实现深拷贝
🔔注意:Citation类和Student类必须实现Serializable接口,否则会抛NotSerializableException异常。

public class Student implements Serializable {
    private String name;
    private String address;
    public Student(String name,String address) {//构造方法
        this.name = name;
        this.address = address;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Citation implements Cloneable, Serializable {
    private Student student;

    public void setStudent(Student student){
        this.student = student;
    }
    public Student getStudent(){
        return student;
    }
    public Citation clone() throws CloneNotSupportedException{
        return (Citation) super.clone();
    }
    public void show(){
        System.out.println(student.getName() + "同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}

public class Test {
    public static void main(String[] args) throws Exception {
        Citation original = new Citation();
        Student student1 = new Student("aaaa","Shanghai");
        original.setStudent(student1);


        //创建对象输出流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\testcode\\a.txt"));//使用序列化方式,前提是实现序列化接口将输出流对象存储再指定位置,
        //将original对象写出到文件中
        oos.writeObject(original);
        oos.close();
        //创建对象出入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\testcode\\a.txt"));
        //读取对象
        Citation clone = (Citation) ois.readObject();
        clone.getStudent().setName("bbbb");//获取clone奖状并修改对象的名字

        System.out.println(original==clone);//原型对象和克隆出来的是否是同一个对象
        System.out.println(original.equals(clone));//原型对象和克隆出来的值是否相等
        System.out.println(original.getClass()==clone.getClass());//原型对象和克隆出来的是否是同一个class
        original.show();
        clone.show();
    }
}
false
false
true
aaaa同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!
bbbb同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!

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

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

相关文章

多线程(5)

文章目录前言 :常见锁策略了1.悲观锁 VS 乐观锁2. 轻量级锁 VS 重量级锁3.自旋锁 VS 挂起等待锁4. 读写锁 VS 普通的互斥锁5. 公平锁 和 非公平锁6. 可重入锁 VS 不可重入锁CAS1. CAS 的应用场景2. CAS 的典型问题 : ABA 问题synchronized 原理1.锁升级 / 锁膨胀2.锁…

Ae 效果详解:发光

效果/风格化/发光Effects/Stylize/Glow发光 Glow效果可找到图像中的较亮部分,然后使那些像素和周围的像素变亮,以创建漫射的发光光环。可以创建两种颜色(颜色 A 和颜色 B )之间的渐变发光,并可通过复制发光效果以创建更…

RESTful开发风格 与 SpringMVC跨域访问

RESTful REST:表现层状态转换,资源在网络中以某种表现形式进行状态转移RESTful 是基于 REST理念 的一套开发风格,是具体的开发规则,如果一个架构符合REST 原则,就称为 RESTful 架构。 RESTful 开发规范:…

【leetcode】学了栈和队列却觉得无用武之地?试试这几道题目吧!

目录 0.写在前面 1.leetcode.20 有效的括号 2.leetcode.225 用队列实现栈 3.用栈实现队列 4.设计循环队列 0.写在前面 这些题目所用语言为C语言,由于C语言未提供栈和队列的数据结构,所以需要我们手动实现栈和队列。此外熟练掌握栈和队列的性质对解…

【C++】从0到1入门C++编程学习笔记 - 实战篇:职工管理系统

文章目录一、需求分析二、创建项目2.1 创建新项目2.2 添加文件三、创建管理类3.1 创建文件3.2 头文件实现3.3 源文件实现四、菜单功能4.1 添加成员函数4.2 菜单功能实现4.3 测试菜单功能五、退出功能5.1 提供功能接口5.2 实现退出功能5.3 测试功能六、创建职工类6.1 创建职工抽…

虚拟机克隆两网卡冲突

常见网卡设置 vim /etc/sysconfig/network-scripts/ifcfg-ens33TYPEEthernet BOOTPROTOstatic DEFROUTEyes NAMEens33 UUID025f7880-7357-4148-ae5a-a629d597c133 DEVICEens33 ONBOOTyes DNS18.8.8.8 IPADDR 192.168.100.16 GATEWAY192.168.100.254 NETMASK255.255.255.0有的版…

25/365 java 守护线程 线程同步 synchronized

1.守护线程 线程分为守护线程和用户线程 : daemon thread and non-daemon thread 虚拟机必须等待用户线程执行完毕,但无需等待守护线程执行完毕。 守护线程举例:垃圾回收线程,监控内存线程。 setDaemon(true):默认为false,默…

【LeetCode:121. 买卖股票的最佳时机~~~动态规划】

题目描述 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的…

【微信小程序】文章点赞功能的实现

🏆今日学习目标:第二十期——文章点赞功能的实现 ✨个人主页:颜颜yan_的个人主页 ⏰预计时间:15分钟 🎉专栏系列:我的第一个微信小程序 文章目录前言效果图实现步骤总结前言 哈喽大家好,本期是…

Unity简单几行代码让玩家水平移动更丝滑真实

可以先来看看基础的移动代码,接收玩家的输入,然后赋予刚体速度。 但是这种写法存在几个问题,下面一一纠正。 首先,如果直接改变刚体的速度,那么可能会出现穿墙的问题。 而且没有一种从速度0到缓慢加速的过程&#xff…

自定义Filter后,我的业务代码怎么被执行了多次?

若要求构建的过滤器针对全局路径有效,且无任何特殊需求(主要针对 Servlet 3.0 的一些异步特性),则完全可直接使用 Filter 接口(或继承 Spring 对 Filter 接口的包装类 OncePerRequestFilter),并…

分享130个ASP源码,总有一款适合您

ASP源码 分享130个ASP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下..., 130个ASP源码下载链接:https://pan.baidu.com/s/13ZxaHPHdgorjGV1wWvx1WQ?pwd7z4p 提取码&#x…

07_FreeRTOS任务调度器的挂起和恢复

任务调度器的挂起和恢复 挂起任务调度器,调用此函数不需要关闭中断 使用格式示例: 1.与临界区不一样的是,挂起任务调度器,未关闭中断; 2.它仅仅是防止;饿任务之间的资源争夺,中断照样可以直接响应; 3.挂起调度器的方式,适合于临界区位于任务与任务之间;既不用去延…

MySQL 8.0.31 集合操作INTERSECT和EXCEPT

对于聚合的功能MySQL是都是默默的发展。在最新的8.0.31版本中提供对集合操作INTERSECT和EXCEPT。这样一来,集合操作功能基本圆满了。MySQL5.7.40版本是不支持这个集合的。 In this release MySQL adds support for the SQL standard INTERSECT and EXCEPT table op…

Linux常用命令——ssh命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) ssh openssh套件中的客户端连接工具 补充说明 ssh命令是openssh套件中的客户端连接工具,可以给予ssh加密协议实现安全的远程登录服务器。 语法 ssh(选项)(参数)选项 -1:强制使用ssh协…

基于FPGA的时间数字转换(TDC)设计(四)

1. 基于IODELAY的TDC设计原理 在第一篇中讲过,基于FPGA开发的TDC常见的有直接计数法,多相位时钟采样法,抽头延迟线法等等。前面3篇讲解了基于多相位的TDC,接下来主要讲解基于抽头延迟线的方法。在Xilinx FPGA开发中,要实现抽头延迟线,主要由进位链(Carry4)和IODELAY模块…

寒假题练——day(6)

题目1: 有一种兔子,从出生后第3个月起每个月都生一只兔子, 小兔子长到第三个月后每个月又生一只兔子。 例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。 一月的时候有一只兔子,假如兔…

检索方案优化

文章目录 1. Flab框架概览2. Flab框架各个层在基金检索的具体应用2.1. 前置检查Check层2.2. 多路召回Recall层2.3. 结果集过滤2.3.1. 问财和我们召回结果的交集2.4. 排序Rank2.5. 缓存Cache2.6. 封装Assmeble1. Flab框架概览 Fly like a bird 寓意灵活 2. Flab框架各个层在基金…

2023年大年初一 —— 牛客网刷题经验分享~

2023年大年初一 —— 牛客网刷题经验分享~😎大年初一 —— 牛客网刷题经验分享~😎)前言🙌BC94 反向输出一个四位数 😊BC95 小乐乐与进制转换 😊BC96 [NOIP2015]金币😊BC97 回文对称数 😊总结撒花…