设计模式--原型模式
目录
基本介绍
传统方式克隆
原型模式改进
浅拷贝和深拷贝
浅拷贝的介绍
深拷贝的介绍
原型模式的注意事项和细节
基本介绍
(1) 原型模式(prototype模式): 用原型实例指定创建对象的种类 并且通过拷贝这些原型 创建新的对象
(2) 原型模式是一种创建型设计模式 允许一个对象再创建另一个可定制的对象 而不需要知道如何创建的细节
(3) 工作原理: 通过将一个原型对象传给那个要发动创建的对象 这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建 即对象.clone()
传统方式克隆
(1) 优点是简单易操作 比较好理解
(2) 在创建新的对象时 总是需要重新获取原始对象的属性 如果创建的对象比较复杂时 效率较低
(3) 总是需要重新初始化对象 而不是动态地获得对象运行时的状态 不够灵活
(4)改进思路分析
java中Object类是所有类的基类 Object类提供了一个clone()方法 该方法可以将一个java对象复制一份 但是需要实现clone的java类必须要实现一个接口Cloneable 该接口表示该类能够复制且具有复制的能力-->原型模式
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Monkery {private String name;private Integer age;private String color;}
测试结果:
原型模式改进
要克隆的实例实现Cloneable接口并实现默认的clone方法
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MonkeyClone implements Cloneable{private String name;private Integer age;private String color;//克隆该实例 使用默认的clone方法实现@Overrideprotected Object clone() {MonkeyClone monkeyClone = null;try {monkeyClone = (MonkeyClone)super.clone();}catch (Exception e){System.out.println(e.getMessage());}return monkeyClone;}
}
测试结果:
浅拷贝和深拷贝
浅拷贝的介绍
(1) 对于数据类型是基本数据类型的成员变量 浅拷贝会直接进行值传递 也就是将该属性值复制一份给新的对象
(2) 对于数据类型是引用数据类型的成员变量 比如说成员变量是某个数组 某个类的对象等 那么浅拷贝会进行引用传递 也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象 因为实际上两个对象的该成员变量都指向同一个实例 在这种情况下 在一个对象中修改该成员变量的话会影响其他对象的该成员变量值
(3) 前面的克隆monkey就是浅拷贝
(4) 浅拷贝是使用默认的clone()方法来实现 monkey=(MonkeyClone) super.clone();
为MonkeyClone 添加一个MonkeryClone类型的child属性 此时这个数据类型即为引用类型
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MonkeyClone implements Cloneable{private String name;private Integer age;private String color;private MonkeyClone child;public MonkeyClone(String name, Integer age, String color) {this.name = name;this.age = age;this.color = color;}//克隆该实例 使用默认的clone方法实现@Overrideprotected Object clone() {MonkeyClone monkeyClone = null;try {monkeyClone = (MonkeyClone)super.clone();}catch (Exception e){System.out.println(e.getMessage());}return monkeyClone;}
}
我们接下来看引用数据类型的clone特性:
测试
我们这里可以看到,后面复制的monke它们的hashCode都是一致的,说明它们的内存地址指向的都是同一个地址
深拷贝的介绍
(1) 复制对象的所有基本数据类型的成员变量值
(2) 为所有引用数据类型的成员变量申请储存空间 并复制每个引用数据类型成员变量所引用的对象 直到该对象可达的所有对象 也就是说 对象进行深拷贝要对整个对象进行拷贝
(3) 深拷贝的实现方式1: 重写clone方法来实现深拷贝
(4) 深拷贝的实现方式2: 通过对象序列化来实现深拷贝
public class DeepCloneTarget implements Serializable,Cloneable {private String cloneName;private String cloneClass;public DeepCloneTarget(String cloneName, String cloneClass) {this.cloneName = cloneName;this.cloneClass = cloneClass;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
@Data
@Accessors(chain = true)
public class DeepProtoType implements Serializable,Cloneable {String name; //String 属性DeepCloneTarget deepCloneTarget; //引用类型public DeepProtoType() {super();}//深拷贝 方式1 使用clone方法@Overrideprotected Object clone() throws CloneNotSupportedException {Object deep = null;//这里完成对基本数据类型(属性)和String的克隆deep = super.clone();//对引用类型的属性 进行单独处理DeepProtoType deepProtoType =(DeepProtoType) deep;deepProtoType.deepCloneTarget = (DeepCloneTarget) deepCloneTarget.clone();return deepProtoType;}
}
方式二:
@Data
@Accessors(chain = true)
public class DeepProtoType implements Serializable,Cloneable {String name; //String 属性DeepCloneTarget deepCloneTarget; //引用类型public DeepProtoType() {super();}//深拷贝 方式1 使用clone方法@Overrideprotected Object clone() throws CloneNotSupportedException {Object deep = null;//这里完成对基本数据类型(属性)和String的克隆deep = super.clone();//对引用类型的属性 进行单独处理DeepProtoType deepProtoType =(DeepProtoType) deep;deepProtoType.deepCloneTarget = (DeepCloneTarget) deepCloneTarget.clone();return deepProtoType;}//深拷贝 方式2 通过对象序列化实现(推荐)public Object deepClone(){//创建流对象ByteArrayOutputStream bos = null;ObjectOutputStream oos = null;ByteArrayInputStream bis = null;ObjectInputStream ois = null;try{//序列化bos = new ByteArrayOutputStream();oos = new ObjectOutputStream(bos);oos.writeObject(this); //当前这个对象以对象流的方式输出//反序列化bis = new ByteArrayInputStream(bos.toByteArray());ois = new ObjectInputStream(bis);DeepProtoType copyObj = (DeepProtoType) ois.readObject();return copyObj;}catch (Exception e){e.printStackTrace();return null;}finally {//关闭流try {bos.close();oos.close();ois.close();bis.close();}catch (Exception ee){System.out.println(ee.getMessage());}}}
}
测试
原型模式的注意事项和细节
(1) 创建新的对象比较复杂时 可以利用原型模式简化对象的创建过程 同时也能够提高效率
(2) 不用初始化对象 而是动态地获得对象运行时的状态
(3) 如果原始对象发生变化(增加或者减少属性) 其他克隆对象的也会发生相应的变化 无需修改代码
(4) 在实现深克隆的时候可能需要比较复杂的代码
(5) 缺点: 需要为每一个类配备一个克隆方法 这对全新的类来说不是很难 但对已有的类进行改造时 需要修改其源码 违背了ocp原则
相关文章:

设计模式--原型模式
目录 基本介绍 传统方式克隆 原型模式改进 浅拷贝和深拷贝 浅拷贝的介绍 深拷贝的介绍 原型模式的注意事项和细节 基本介绍 (1) 原型模式(prototype模式): 用原型实例指定创建对象的种类 并且通过拷贝这些原型 创建新的对象 (2) 原型模式是一种创建型设计模式 允许一个…...

C++智能指针shared_ptr详解
智能指针shared_ptr详解 一、简介二、底层原理2.1、引用计数2.2、shared_ptr的构造和析构2.3、shared_ptr的共享和拷贝2.4、循环引用问题 三、shared_ptr的使用3.1、创建一个shared_ptr3.2、共享一个shared_ptr3.3、使用删除器3.4、解除关联 四、使用示例总结 一、简介 C智能指…...

家政服务APP小程序开发功能详解
随着人们生活水平的提高,对家政服务的要求也越来越高。而传统的到家政公司寻找服务人员的方法显然已经无法满足人们需求,取而代之的是线上预约家政服务。家政服务App小程序软件可以满足用户在线预约,还可以根据自己的需求定制家政服务、选择家…...

【C++】deque的实现原理简单介绍
前言 deque被称为双端队列,它的出现主要是为了结合vector和list的优点并减小它们的缺点,实际上deque确实结合了vector和list的优点减小了它们的缺点,但是它的结合也让它自己的优点没有原始的vector和list那么极致,导致deque变得很…...

UWB隧道人员定位技术应用,施工作业安全精准保障
隧道施工的安全不仅关系到工程项目的质量和施工效率,也关系到我国的资金安全、施工人员和人民的生命财产安全。如何有效加强隧道施工的安全管理能力,成为隧道施工企业管理者最关心的问题。国家铁道局在《关于加强铁路隧道工程安全工作的若干意见》中指出…...

15.2 矩阵链乘法
1.代码 public class MatrixChainMultiplication {public static void main(String[] args) { // 在该代码中,我们首先创建了两个n * n的矩阵m和s,分别用于记录最优值和分割点。 其中m 矩阵 通过i j 来显示在i到j的矩阵链中最优解 // // …...

向隐形冠军学习:聚焦人效,用时间管理提效益
注: 本文来源于盖雅工场联合创始人兼CEO 章新波 在2023狮山论坛“ 向隐形冠军学习: 聚焦人效,用时间管理提效益 ”的主题分享。 文|章新波 整理 |盖雅学苑 在人力资源行业以及各大企业,「人效」这个词…...

Protocol Buffers Go Generated Code Guide
Protocol Buffers Go 代码生成指南 本主题准确描述了协议缓冲区编译器为任何给定的协议定义生成的Go代码。 编译器调用 协议缓冲区编译器需要一个插件来生成Go 代码。使用Go 1.16或更高版本安装,方法是运行: go install google.golang.org/protobuf/…...

Python VTK STL 映射三维模型表面距离
目录 前言: 效果: 实现步骤: Code: 前言: 本文介绍了Python VTK映射三维模型表面距离,通过如何使用VTK计算两个三维模型(stl)的表面距离,并将其距离值以颜色映射到模型,可用于对比 两相模型…...

C# 异常处理机制和常见的异常类型
在 C# 中,异常处理是一个非常重要的概念,它可以让我们在程序发生错误时进行有效的处理,使程序具备更好的鲁棒性。C# 异常处理机制基于 try-catch-finally 语句块,其基本用法如下: try {// 可能会抛出异常的代码 } cat…...

【0187】客户端身份验证配置文件视图之pg_hba_file_rules
文章目录 1. 客户端身份验证配置文件视图2. 视图效果相关阅读: 【0179】配置PostgreSQL以允许远程连接 【0180】PG内核通过pg_hba.conf完成客户端认证(1) 【0181】PG内核通过pg_hba.conf完成客户端认证(2)...

模糊层次分析法(FAHP)Python实现
文章目录 理论基础三角模糊数概念参考 Python源码测试 理论基础 \quad 模糊层次分析法( F A H P FAHP FAHP)将模糊理论( F u z z y S e t Fuzzy Set FuzzySet)嵌入到基本层次分析法( A H P AHP AHP)中。 A …...

gdb切换窗口焦点
为了辅助调试,一般会使用layout src,调起TUI显示代码: 然而这种情况下我们写命令很不方便,无法方便地使用上一条命令、退格等。 按动上下左右方向键盘只会移动代码框,然而在伪终端下,可以用鼠标滚轮来上下…...

【Spring Security】 入门实战
文章目录 一、基本概念二、Spring Security第一个程序三、Spring Security没有生效四、修改默认账号密码(appliction.yml)五、修改默认账号密码(配置类)六、Spring Security的三个configure方法七、Spring Security的三种身份的验…...

SpringBoot的Interceptor拦截器的简介和实际使用
拦截器(Interceptor) 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。 作用:拦截请求,在指定的方法调用前后,根据业务需要执行…...

5个面向Python高级开发者的技巧
使用这些用于自定义类行为、编写并发代码、管理资源、存储和操作数据以及优化代码性能的高级技术来探索 Python 的深度。 本文探讨了 Python 中的五个高级主题,它们可以为解决问题和提高代码的可靠性和性能提供有价值的见解和技术。从允许您在定义类时自定义类行为的…...

Nginx简介
Nginx是什么?可以做什么事情? Nginx是高性能的HTTP和反向代理的web服务器,处理高并发的能力十分强大,能经受高负载的考研,有报告表明能能支持高达50000个并发连接数。 特点 占有内存少:一万个长连接&…...

十五分钟带你学会 Electron
文章目录 什么是 Electron为什么要选择 Electron安装 Electron桌面CSDN实战Electron 基础配置Electron 进程主进程渲染进程主进程与渲染进程的区别主进程与渲染进程的通信 Electron 跨平台问题Electron 部署打包应用程序发布应用程序 Electron 跨端原理总结 什么是 Electron E…...

设计模式-结构型模式之桥接模式
2. 桥接模式 2.1. 模式动机 设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案: 第一种设计方案是为每一种形状…...

软件测试工程师为什么要写测试用例?
软件测试工程师为什么要写测试用例?相信从事软件测试行业的从业者来讲,测试用例并不陌生。因为测试用例不仅仅是一组简单的文档,它包含前提条件、输入、执行条件和预期结果等等重要内容,并且能够完成一定的测试目的和需求。下面本…...

【DAY40】VUE练习
DOS命令: DOS(Disk Operating System)是一种操作系统,它使用命令行界面(Command Prompt)进行交互。在 DOS 中,有一些常用的命令,可以用来定位目录、创建、删除、拷贝文件和目录&…...

实模式的寄存器
实模式的寄存器有8个通用寄存器,分别为AX、BX、CX、DX、SI、DI、BP和SP。通用的意思就是它们之中的大部分可以根据需要用于多种目的。 AX: accumulator,累加寄存器 BX: base,基址寄存器 CX: count,计数寄存器 SI: Source Index&am…...

【UE 控件蓝图】通过键盘选中要点击的按钮 通过Enter键点击
上一篇【UE 控件蓝图】菜单及功能实现博客已经完成了菜单的制作,但是我们只能通过鼠标来点击菜单选项,本篇博客实现的是能够通过键盘的上下键来选中按钮,然后按下“Enter”键来实现点击按钮的效果。 效果 可以看到并没有移动鼠标也可以通过…...

SSR在天猫优品大促会场的探索实践
BBC 发现其网站加载时间每增加一秒,用户便会流失 10%。为提高页面的秒开率,我们不断探索着优化策略,仅仅在浏览器领域下的优化已经满足不了我们的极致要求,开始往服务端方向不断探索。本文将讨论业务接入SSR的几个问题:…...
WPF教程(一)---创建一个WPF程序基础知识
1.前言: 这篇主要讲WPF的开发基础,介绍了如何使用Visual Studio 2019创建一个WPF应用程序。 首先说一下学习WPF的基础知识: 1) 要会一门.NET所支持的编程语言--例如C#。 2) 会一点“标准通用标记语言”:WPF窗体程序使用的XAML语…...

【C++ 四】函数、指针
函数、指针 文章目录 函数、指针前言1 函数1.1 概述1.2 函数定义1.3 函数调用1.4 值传递1.5 函数常见样式1.6 函数声明1.7 函数分文件编写1.8 函数默认参数1.9 函数占位参数1.9 函数重载1.9.1 函数重载概述1.9.2 函数重载注意事项 2 指针2.1 指针基本概念2.2 指针变量定义和使用…...

虚拟人与娱乐传媒融合,推动综艺新模式
经过多年的更新迭代和市场的推动,虚拟人技术正在逐渐迈向成熟:3D虚拟形象的制作变得越来越精致且真实,并且出现了越来越多功能丰富使用便捷的动捕设备。因此,包括综艺影视在内的诸多领域,开始尝试将虚拟人技术融入行业…...

Linux_红帽8学习笔记分享_5
Linux_红帽8学习笔记分享_5 文章目录 Linux_红帽8学习笔记分享_51. UMASK反掩码1.1如何查看反掩码umask1.2 UMASK反掩码的作用1.2.1对于目录来说1.2.2对于文件来说 1.3如何修改UMASK反掩码1.4普通用户反掩码的测试 2.whereis的使用3. SUID权限弥补(主要针对文件,所有者执行位变…...

网络编程及项目思路
计算机和计算机之间通过网络进行数据传输 常见的软件架构: C/S:客户端/服务器 画面可以做的非常精美,用户体验好需要开发客户端,也需要开发服务端用户需要下载和更新的时候太麻烦 B/S:浏览器/服务器 不需要开发客户端,只需要…...

GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相操作
写在前面 本文主要针对使用GD(兆易创新)系列的FLASH做启动配置片时,遇到的相关问题进行简单整理复盘,避免后人踩坑。 本人操作固化芯片型号为:ZYNQ7045、690T(复旦微替代型号V7 690T)。 7系列…...