设计模式之原型模式【创造者模式】

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您:
想系统/深入学习某技术知识点…
一个人摸索学习很难坚持,想组团高效学习…
想写博客但无从下手,急需写作干货注入能量…
热爱写作,愿意让自己成为更好的人…

文章目录

  • 前言
  • 一、概述
  • 二、结构
  • 三、实现
  • 四、案例
  • 五、使用场景
  • 六、扩展(深克隆)
  • 总结


前言

一、概述
二、结构
三、实现
四、案例
五、使用场景
六、扩展(深克隆)


一、概述

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

二、结构

原型模式包含如下角色:

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

接口类图如下:
在这里插入图片描述

三、实现

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

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

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

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

Realizetype(具体的原型类):

public class Realizetype implements Cloneable {public Realizetype() {System.out.println("具体的原型对象创建完成!");}@Overrideprotected Realizetype clone() throws CloneNotSupportedException {System.out.println("具体原型复制成功!");return (Realizetype) super.clone();}
}

Client (测试访问类):

public class Client {public static void main(String[] args) throws CloneNotSupportedException {//创建一个原型类对象Realizetype r1 = new Realizetype();//调用Realizetype类中的clone方法进行对象的克隆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 + "同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");}@Overridepublic 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 String name;
//
//    public String getName() {
//        return name;
//    }
//
//    public void setName(String name) {
//        this.name = name;
//    }private Student stu;public Student getStu() {return stu;}public void setStu(Student stu) {this.stu = stu;}public void show() {System.out.println(stu.getName() + "同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");}@Overridepublic Citation clone() throws CloneNotSupportedException{return (Citation) super.clone();}}//学生类
public class Student {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +'}';}
}//测试类
public class CitationTest {public static void main(String[] args) throws CloneNotSupportedException {//1、创建原型对象Citation c1 = new Citation();Student stu=new Student();stu.setName("张三");c1.setStu(stu);
//        c1.setName("张三");//复制奖状对象Citation c2 = c1.clone();Student stu1=c2.getStu();stu1.setName("李四");//将奖状的名字修改李四
//        c2.setName("李四");c1.show();c2.show();}
}

在这里插入图片描述

此时之所以名字会相同是因为Citation类此时复制的是Student类【引用类型】,引用类型是同一个地址,而原本的Citation类中是String类型【基础类型】,并不是同一块地址。

运行结果为:
在这里插入图片描述
说明:

​ stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个Citation(奖状)对象中显示的都是李四。这就是浅克隆的效果,对具体原型类(Citation)中的引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流。代码如下:

public class CitationTest {public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {//1、创建原型对象Citation c1 = new Citation();Student stu=new Student();stu.setName("张三");c1.setStu(stu);//创建对象输出流对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\b.txt"));//将c1对象写出到文件中oos.writeObject(c1);oos.close();//创建对象出入流对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\Lenovo\\Desktop\\b.txt"));//读取对象Citation c2 = (Citation) ois.readObject();//释放资源ois.close();//获取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.hqwc.cn/news/319597.html

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

相关文章

2023年.AI域名销售额达550万美元 2024还要继续涨

根据域名投资专家Elliot Silver的最新文章,2023年公开报道的.AI域名销售额已经达到了550万美元,而2022年和2021年分别为90万美元和120万美元。 Silver观察到过去几年.AI域名销售额呈现逐年增长的趋势,尤其是2023年的销售额相较前两年有了显著…

高效的输电线路故障监测系统:实时监测、预防性维护

在电力系统中,输电线路的健康状态直接关系到电网的安全稳定运行。然而,由于线路的广泛分布和长距离特性,故障的检测和定位变得极其困难。为了解决这一问题,恒峰智慧设计了一种全新的高效输电线路故障监测系统,该系统采…

进程和计划任务

一、什么是程序 是一组计算机能识别和执行的指令,运行于电子计算机上,满足人们某种需求的信息化工具 用于描述进程要完成的功能,是控制进程执行的指令集 二、进程 1.什么是进程 进程:正在运行中的程序,加载到内存…

静态网页课程设计——十二花信(花朵科普)(HTML+CSS+JavaScript)

前言 使用技术:HTMLCSSJS 主要内容:对十二个月每个月的适应季节的花朵进行科普。 主要内容 1、首页 首页顶部由标题栏和一张花朵的图片组成。 下半部分对十二花信进行了简单的科普介绍,分别为一月梅花、二月杏花、三月桃花等等。。 部…

Java 跨平台实现

Java 跨平台实现 1. Java虚拟机(JVM)2. 中间代码(字节码)3. Write Once, Run Anywhere (WORA)4. Java 标准库5. 安全性与隔离6. Java Community Process (JCP) Java 的跨平台性主要是通过以下几个关键机制来实现的: 1…

Java设计模式:状态模式

❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得关注、点赞、收藏、…

天融信TOPSEC Cookie 远程命令执行漏洞

产品介绍 天融信TopSec 安全管理系统,是基于大数据架构,采用多种技术手段收集各类探针设备安全数据,围绕资产、漏洞、攻击、威胁等安全要素进行全面分析,提供统一监测告警、集中策略管控、协同处置流程,实现客户等保合…

GZ075 云计算应用赛题第5套

2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷5 某企业根据自身业务需求,实施数字化转型,规划和建设数字化平台,平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”,拟采用开源OpenSt…

Vue: 多个el-select不能重复选择相同属性

一、场景 1.需求&#xff1a; 用户可自由选择需要修改的对象并同时修改多个属性&#xff0c;需要校验修改对象不能重复选择&#xff0c;但是可供修改属性是固定的 2.目标效果&#xff1a; 二、实现 1.主要代码&#xff1a; <template><el-selectv-model"se…

SV-DJS-I13 深圳锐科达电梯 IP 五方对讲规格书

SV-DJS-I13 深圳锐科达电梯 IP 五方对讲规格书 DJS-I13 是专门对行业用户需求研发的一款 SIP 电梯五方对讲。它不仅有稳定性 好、电信级音质的优点&#xff0c;且完美兼容当下所有基于 SIP 的主流 IPPBX/软交换/IMS 平台, 如 Asterisk, Broadsoft, 3CX, Elastix 等。它集…

redis 三主六从高可用dockerswarm高级版(不固定ip)

redis集群(cluster)笔记 redis 三主三从高可用集群docker swarm redis 三主六从高可用docker(不固定ip) redis 三主六从高可用dockerswarm高级版(不固定ip) 此博客解决&#xff0c;redis加入集群后&#xff0c;是用于停掉后重启&#xff0c;将nodes.conf中的旧的Ip替换为新的…

【C语言进阶篇】 数组常考笔试题万字解析(下)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言&#x1f4ac; 数组笔试题解析&#x1f4ad; 字符数组笔试题✅ 字符数组笔试题解析 &#x1…