当前位置: 首页 > news >正文

10 创建型模式-原型模式

引言:
创建对象的五种方式:

  1. 通过new关键字
  2. 通过Class类的newInstance()方法
  3. 通过Constructor类的newInstance()方法
  4. 利用Clone方法
  5. 反序列化

Clone方法:
其实现方式正是通过调用 Object 类的 clone() 方法来完成。

protected native Object clone() throws CloneNotSupportedException;
public class Person implements Cloneable{public String pname;public int page;public Address address;public Person() {}public Person(String pname,int page){this.pname = pname;this.page = page;this.address = new Address();}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public void setAddress(String provices,String city ){address.setAddress(provices, city);}public void display(String name){System.out.println(name+":"+"pname=" + pname + ", page=" + page +","+ address);}public String getPname() {return pname;}public void setPname(String pname) {this.pname = pname;}public int getPage() {return page;}public void setPage(int page) {this.page = page;}}
public class Address {private String provices;private String city;public void setAddress(String provices,String city){this.provices = provices;this.city = city;}@Overridepublic String toString() {return "Address [provices=" + provices + ", city=" + city + "]";}}

这是一个我们要进行赋值的原始类 Person。下面我们产生一个 Person 对象,并调用其 clone 方法复制一个新的对象。
注意:调用对象的 clone 方法,必须要让类实现 Cloneable 接口,并且覆写 clone 方法。
测试:

@Test
public void testShallowClone() throws Exception{Person p1 = new Person("zhangsan",21);p1.setAddress("湖北省", "武汉市");Person p2 = (Person) p1.clone();System.out.println("p1:"+p1);System.out.println("p1.getPname:"+p1.getPname().hashCode());System.out.println("p2:"+p2);System.out.println("p2.getPname:"+p2.getPname().hashCode());p1.display("p1");p2.display("p2");p2.setAddress("湖北省", "荆州市");System.out.println("将复制之后的对象地址修改:");p1.display("p1");p2.display("p2");
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

深拷贝

在这里插入图片描述
在这里插入图片描述

如何实现深拷贝?
  1. 让每个引用类型属性内部都重写clone() 方法
  2. 利用序列化
1 原型模式介绍

定义: 原型模式(Prototype Design Pattern)用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。

西游记中的孙悟空 拔毛变小猴,孙悟空这种根据自己的形状复制出多个身外化身的技巧,在面向对象软件设计领域被称为原型模式.孙悟空就是原型对象.
在这里插入图片描述
在这里插入图片描述

2 原型模式原理

在这里插入图片描述
在这里插入图片描述

3 深克隆与浅克隆

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3) 浅克隆代码实现:

在这里插入图片描述
测试

@Test
public void test01() throws CloneNotSupportedException {ConcretePrototype c1 = new ConcretePrototype();ConcretePrototype c2 = c1.clone();//输出falseSystem.out.println("对象c1和c2是同一个对象?" + (c1==c2));
}
4) 深克隆代码实现
/*** 具体原型类* 实现Cloneable标识接口,表示当前类对象可复制**/
public class ConcretePrototype implements Cloneable, Serializable {private Person person;public Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}public void show(){System.out.println("嫌疑人姓名: " + person.getName());}public ConcretePrototype() {System.out.println("具体原型对象创建成功!");}@Overrideprotected ConcretePrototype clone() throws CloneNotSupportedException {System.out.println("克隆对象复制成功!");return (ConcretePrototype) super.clone();}
}
import java.io.Serializable;public class Person implements Serializable {private String name;public Person() {}public Person(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
//浅拷贝@Testpublic void test02() throws CloneNotSupportedException {ConcretePrototype c1 = new ConcretePrototype();Person p1 = new Person("峰哥");c1.setPerson(p1);//复制c1ConcretePrototype c2 = c1.clone();Person p2 = c2.getPerson();p2.setName("凡哥");c1.show();c2.show();//输出true,克隆对象和原型对象还是共享name属性的System.out.println("对象p1和对象p2是同一个对象吗?" + (p1 == p2));}

如果有需求场景中不允许共享同一对象,那么就需要使用深拷贝,如果想要进行深拷贝需要使用到对象序列化流 (对象序列化之后,再进行反序列化获取到的是不同对象).
在这里插入图片描述

4 原型模式应用实例

在这里插入图片描述
在这里插入图片描述

代码实现
广告模板代码
/*** 广告模板**/
public class AdvTemplate {//广告信名称private String advSubject = "xx银行本月还款达标,可抽iPhone 13等好礼!";//广告信内容private String advContext = "达标用户请在2022年3月1日到2022年3月30日参与抽奖......";public String getAdvSubject() {return advSubject;}public void setAdvSubject(String advSubject) {this.advSubject = advSubject;}public String getAdvContext() {return advContext;}public void setAdvContext(String advContext) {this.advContext = advContext;}
}

邮件类代码

/*** 邮件类**/
public class Mail {private String receiver; //收件人private String subject; //邮件名称private String appellation; //称呼private String context;  //邮件内容private String tail; //邮件尾部 "xx版权所有"public Mail(AdvTemplate advTemplate) {this.subject = advTemplate.getAdvSubject();this.context = advTemplate.getAdvContext();}public String getReceiver() {return receiver;}public void setReceiver(String receiver) {this.receiver = receiver;}public String getSubject() {return subject;}public void setSubject(String subject) {this.subject = subject;}public String getAppellation() {return appellation;}public void setAppellation(String appellation) {this.appellation = appellation;}public String getContext() {return context;}public void setContext(String context) {this.context = context;}public String getTail() {return tail;}public void setTail(String tail) {this.tail = tail;}
}

客户类

/*** 业务场景**/
public class Client {//发送邮件的数量private static int MAX_COUNT = 6;//发送邮件public static void sendMail(Mail mail){System.out.println("标题: " + mail.getSubject() + "\t 收件人: " + mail.getReceiver()+ "\t ...发送成功!");}public static void main(String[] args) {int i = 0;//定义模板Mail mail = new Mail(new AdvTemplate());mail.setTail("xxx银行版权所有");while(i < MAX_COUNT){//每封邮件不同的信息mail.setAppellation(" 先生 (女士)");Random random = new Random();int num = random.nextInt(999999999);mail.setReceiver(num + "@"+"mashibing.com");//发送邮件sendMail(mail);i++;}}}

在这里插入图片描述
代码重构
Mail类

public class Mail implements Cloneable {private String receiver; //收件人private String subject; //邮件名称private String appellation; //称呼private String context;  //邮件内容private String tail; //邮件尾部 "xx版权所有"public Mail(AdvTemplate advTemplate) {this.subject = advTemplate.getAdvSubject();this.context = advTemplate.getAdvContext();}public String getReceiver() {return receiver;}public void setReceiver(String receiver) {this.receiver = receiver;}public String getSubject() {return subject;}public void setSubject(String subject) {this.subject = subject;}public String getAppellation() {return appellation;}public void setAppellation(String appellation) {this.appellation = appellation;}public String getContext() {return context;}public void setContext(String context) {this.context = context;}public String getTail() {return tail;}public void setTail(String tail) {this.tail = tail;}@Overrideprotected Mail clone() {Mail mail = null;try {return  (Mail)super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();return null;}}
}

Client类

public class Client {//发送邮件的数量private static int MAX_COUNT = 6;//发送邮件public static void sendMail(Mail mail){System.out.println("标题: " + mail.getSubject() + "\t 收件人: " + mail.getReceiver()+ "\t ...发送成功!");}public static void main(String[] args) {int i = 0;//定义模板Mail mail = new Mail(new AdvTemplate());mail.setTail("xxx银行版权所有");while(i < MAX_COUNT){//每封邮件不同的信息Mail cloneMail = mail.clone();cloneMail.setAppellation(" 先生 (女士)");Random random = new Random();int num = random.nextInt(999999999);cloneMail.setReceiver(num + "@"+"mashibing.com");//发送邮件sendMail(cloneMail);i++;}}
}
5 原型模式总结

原型模式的优点:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原型模式缺点:
需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时需要修改源代码,违背了开闭原则.

使用场景

在这里插入图片描述

相关文章:

10 创建型模式-原型模式

引言&#xff1a; 创建对象的五种方式&#xff1a; 通过new关键字通过Class类的newInstance()方法通过Constructor类的newInstance()方法利用Clone方法反序列化 Clone方法&#xff1a; 其实现方式正是通过调用 Object 类的 clone() 方法来完成。 protected native Object cl…...

MSQL系列(七) Mysql实战-SQL语句Join,exists,in的区别

Mysql实战-SQL语句Join&#xff0c;exists&#xff0c;in的区别 前面我们讲解了索引的存储结构&#xff0c;BTree的索引结构&#xff0c;以及索引最左侧匹配原则及讲解一下常用的SQL语句的优化建议&#xff0c;今天我们来详细讲解一下 我们经常使用的 join&#xff0c; exist&…...

最新壁纸自动采集系统网站PHP源码/360壁纸官方数据接口采集/ZHEYI采集源码

源码介绍&#xff1a; 最新壁纸自动采集系统网站PHP源码&#xff0c;它是ZHEYI自动采集源码&#xff0c;能够在360壁纸官方数据接口采集。很好用的壁纸网站源码分享&#xff0c;仅供学习&#xff0c;请勿商用。 ZHEYI自动采集壁纸PHP源码&#xff0c;能全自动采集高清壁纸网源…...

Redis在分布式场景下的应用

分布式缓存 缓存的基本作用是在高并发场景下对应服务的保护缓冲 – 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题&#xff1a; redis由于高强度性能采用内存 但是意味着丢失的风险单结点redis并发能力有限分布式服务中数据过多 依赖内存的redis 明显单机不…...

2316. 统计无向图中无法互相到达点对数

2316. 统计无向图中无法互相到达点对数 难度: 中等 来源: 每日一题 2023.10.21 给你一个整数 n &#xff0c;表示一张 无向图 中有 n 个节点&#xff0c;编号为 0 到 n - 1 。同时给你一个二维整数数组 edges &#xff0c;其中 edges[i] [ai, bi] 表示节点 ai 和 bi 之间…...

Selenium定向爬取海量精美图片及搜索引擎杂谈

我自认为这是自己写过博客中一篇比较优秀的文章,同时也是在深夜凌晨2点满怀着激情和愉悦之心完成的。首先通过这篇文章,你能学到以下几点: 1.可以了解Python简单爬取图片的一些思路和方法 2.学习Selenium自动、测试分析动态网页和正则表达式的区别和共同点 …...

面试题—JAVA基础①

文章目录 1.Java面向对象有哪些特征&#xff1f;2.ArrayList和LinkedList有什么区别&#xff1f;3.Java接口和抽象类有哪些区别&#xff1f;4.hashcode和equals如何使用&#xff1f;5.try-catch6.局部变量和实例变量7.String、StringBuffer、StringBuilder 的区别&#xff1f;8…...

naive-ui的n-data-table标签奇特bug记录

具体参考之前的博文&#xff1a;vueday02——使用naive-ui做一个ACM看榜-CSDN博客 具体代码在这里面 原因&#xff1a;在本地运行的时候&#xff0c;datatable里面使用列表渲染成字符串前端设置样式进行转换&#xff0c;但是在正式部署的时候&#xff0c;这个组件没有将其自动…...

微信小程序OA会议系统个人中心授权登入

在我们的完成微信登入授权之前&#xff0c;首先我们要完成我们前面所写的代码&#xff0c;如果有不会的大家可以去看以下我发的前面几个文章链接我发下面了&#xff0c;各位加油&#xff01; 微信小程序OA会议系统数据交互-CSDN博客 微信小程序会议OA系统其他页面-CSDN博客 …...

Git(一)Windows下安装及使用Git Bash

目录 一、简介1.1 什么是Git&#xff1f;1.2 Git 的主要特点1.3 什么是 Git Bash&#xff1f; 二、下载三、安装3.1 同意协议3.2 选择安装位置3.3 其他配置&#xff08;【Next】 即可&#xff09;3.4 安装完毕3.5 打开 Git Bash 官网地址&#xff1a; https://www.git-scm.com/…...

[AUTOSAR][诊断管理][ECU][$19] 读取ECU的DTC故障信息

一、简介 在车载诊断中常用的诊断协议有ISO 14229等&#xff0c;在协议中主要定义了诊断请求、诊断响应的报文格式及ECU该如何处理诊断请求的应用。其中ISO 14229系列标准协议定义了用于行业内诊断通信的需求规范&#xff0c;也就是UDS。UDS主要应用于OSI七层模型的第七层——…...

前端精度问题 (id 返回的和传给后端的不一致问题)

eg: 后端返回 id 10976458979374929 前端获取到的: 10976458979374928 原因: js 中 Number类型范围-2^53 1 到 2^53 - 1 Number.isSafeInteger()用来判断一个整数是否落在这个范围之内。 java中 Long 类型的取值范围是-2^63 1 到 2^63 - 1, 比JavaScript中大很多&#xff0…...

WPF Material Design UI框架

前言 Material Design in xaml 是开源免费的ui框架&#xff0c;工控软件主打的就是简单界面。 以下简称MD 相关资源 MaterialDesignInXamlToolkit Github 地址 MD 快速启动 MD 案例压缩包 MD 框架使用 启动环境配置 安装Nuget包 App.xaml 配置 <Application x:Class&qu…...

C语言求 3*3 矩阵对角线之和

完整代码&#xff1a; // 求 3*3 矩阵对角线之和 #include<stdio.h>int main() {int n3;int arr[3][3];// 输入矩阵printf("请输入矩阵的元素:\n");for (int i 0; i < n; i){for (int j 0; j < n; j){scanf("%d", &arr[i][j]);}}int su…...

缓存分片中的哈希算法与一致性哈希算法

什么是缓存分片 在高并发场景下&#xff0c;缓存往往成为了瓶颈。这时候&#xff0c;我们可以通过缓存数据分片的方式来解决问题。所谓缓存数据分片&#xff0c;就是将缓存数据按照一定的规则分成多个片段&#xff0c;每个片段由不同的缓存节点负责。这样做有两个好处&#xf…...

线框图软件:Balsamiq Wireframes mac中文介绍

Balsamiq Wireframes mac是一款用于创建线框图的软件工具。它旨在帮助用户快速制作出清晰、简洁的界面原型&#xff0c;以便在设计和开发过程中进行协作和沟通。 Balsamiq Wireframes具有简单直观的用户界面&#xff0c;使用户能够快速添加和编辑各种用户界面元素&#xff0c;如…...

【wxWidgets实现透明wxPanel_核心实现_原创思想】

描述 wxWidgets 根本就没有实现过透明wxPanel容器,你设置wxTRANSPARENT_WINDOW,结果sorry 黑色,哈哈哈哈, 就是和你作对.想想当下那么漂亮的桌面, 背景, 透明, 特效.哎 悲哀啊,实现不了,就那死板的界面特性. 网上找了好久,也是乱七八糟,改底层代码还是算了吧,升级特要命.都是只…...

重大技术问题,iPhone 15 Pro Max面临“烧屏门”风波 | 百能云芯

近期&#xff0c;社交媒体平台上陆续涌现大量用户和数码博主就iPhone 15 Pro Max出现烧屏问题的投诉与评论。 烧屏问题是OLED屏幕常见的一个缺陷&#xff0c;这是由OLED屏幕发光机制引发的&#xff0c;OLED屏幕可视为由无数微小的灯泡-像素点构成&#xff0c;这些像素点可以独立…...

深度学习中的不确定性综述

领域学者&#xff1a; http://www.gatsby.ucl.ac.uk/~balaji/ 论文标题&#xff1a; A Survey of Uncertainty in Deep Neural Networks 论文链接&#xff1a; https://arxiv.org/pdf/2107.03342.pdf 概要 在过去的十年中&#xff0c;神经网络几乎遍及所有科学领域&#x…...

uni-app 小宠物 - 会说话的小鸟

在 template 中 <view class"container"><view class"external-shape"><view class"face-box"><view class"eye-box eye-left"><view class"eyeball-box eyeball-left"><span class"…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...