深度学习设计模式之原型模式

ops/2024/10/19 16:38:43/

文章目录

  • 前言
  • 一、介绍
  • 二、详细分析
    • 1.核心组成
      • 浅拷贝
      • 深拷贝
    • 2.实现步骤
    • 3.代码示例
      • 浅拷贝
      • 深拷贝
    • 4.优缺点
      • 优点
      • 缺点
    • 5.使用场景
  • 总结


前言

本文主要学习原型模式原型模式是一种创建对象的模式,原型实例指定创建对象的种类,通过拷贝的方式创建新的对象。


一、介绍

原型模式,是一种对象创建型模式,使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,主要用于创建重复的对象同时又要求性能的情况。

二、详细分析

1.核心组成

  • Prototype: 声明克隆方法的接口,是所有具体原型类的公共父类,Cloneable接口,Serializable接口;
  • ConcretePrototype : 具体原型类;
  • Client: 调用一个原型对象克隆自身从而创建一个新的对象。

浅拷贝

实现cloneable接口,只能拷贝基本数据类型对象
在这里插入图片描述

深拷贝

实现Serializable接口,自定义deepClone方法,通过二进制输入输出实现深拷贝;
在这里插入图片描述

2.实现步骤

  1. 创建具体原型类;
  2. 如果浅拷贝(只能拷贝基本类型)则实现cloneable接口,重写clone方法;如果是深拷贝(除了基本类型,还有引用类型)则实现Serializable接口,自定义序列化方法。
  3. 客户端调用;

3.代码示例

浅拷贝

具体原型类,实现cloneable接口,重写clone方法:


/*** 具体原型类*/
public class Student implements Cloneable {/*** 名字*/private String name;/*** 年龄*/private int age;public Student(){System.out.println("创建学生类");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}/*** 实现 Cloneable colone 方法* @return* @throws CloneNotSupportedException*/@Overrideprotected Student clone() throws CloneNotSupportedException {return (Student) super.clone();}}

客户端:

/*** 客户端*/
public class Client {public static void main(String[] args) throws CloneNotSupportedException {Student student = new Student();student.setAge(18);student.setName("王小明");Student clone = student.clone();clone.setName("韩美美");System.out.println(student.toString());System.out.println(clone.toString());}}

结果:
在这里插入图片描述
通过输出结果,可以发现初始化的构造方法只调用了1次。
浅拷贝存在一个问题,就是只能拷贝基本数据类型,如果使用了引用数据类型,比如集合,或者对象的时候,拷贝将出现问题,如下:
新增加课程集合:

public class Student implements Cloneable {/*** 名字*/private String name;/*** 年龄*/private int age;/*** 课程*/private List<String> clazz = new ArrayList<>();public Student(){System.out.println("创建学生类");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public List<String> getClazz() {return clazz;}public void setClazz(List<String> clazz) {this.clazz = clazz;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", clazz=" + clazz +'}';}/*** 实现 Cloneable colone 方法* @return* @throws CloneNotSupportedException*/@Overrideprotected Student clone() throws CloneNotSupportedException {return (Student) super.clone();}}

客户端:

public class Client {public static void main(String[] args) throws CloneNotSupportedException {Student student = new Student();student.setAge(18);student.setName("王小明");student.getClazz().add("语文");Student clone = student.clone();clone.setName("韩美美");clone.getClazz().add("数学");System.out.println(student.toString());System.out.println(clone.toString());}}

结果:
在这里插入图片描述
发现被克隆的对象的clazz列表也发生了变化,所以得出以下结论:
如果原型对象的成员变量是基本数据类型(int、double、byte、boolean、char等),将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

深拷贝

实现Serializable接口,使用二进制输入输出实现:
具体原型类:

/*** 具体原型类*/
public class Student implements Cloneable,Serializable {/*** 名字*/private String name;/*** 年龄*/private int age;/*** 课程*/private List<String> clazz=new ArrayList<>();public Student(){System.out.println("创建学生类");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public List<String> getClazz() {return clazz;}public void setClazz(List<String> clazz) {this.clazz = clazz;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", clazz=" + clazz +'}';}/*** 实现 Cloneable colone 方法* @return* @throws CloneNotSupportedException*/@Overrideprotected Student clone() throws CloneNotSupportedException {return (Student) super.clone();}/*** 深拷贝* @return*/protected Object deepClone(){try{// 输出 序列化ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(this);// 输入 序列化ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);return objectInputStream.readObject();}catch (Exception e){e.printStackTrace();}return null;}}

客户端:

    public static void main(String[] args) throws CloneNotSupportedException {Student student = new Student();student.setAge(18);student.setName("王小明");student.getClazz().add("语文");Student clone = (Student) student.deepClone();clone.setName("韩美美");clone.getClazz().add("数学");System.out.println(student.toString());System.out.println(clone.toString());}

结果:
在这里插入图片描述
可以看到已经解决了 浅拷贝引用类型,拷贝的问题,得出结论:
无论原型对象的成员变量是基本数据类型还是引用类型,都将复制一份给克隆隆对象。

4.优缺点

优点

  • 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,可以提高新实例的创建效率;
  • 可以使用深拷贝,记录保存当前的状态,随时可恢复历史。

缺点

  • 需要为每一个类都配备一个克隆方法,对已有的类进行改造,需要修改源码,不符合开闭原则;
  • 深拷贝实现比较复杂,当对象之间存在多重的嵌套引用时,需要对每一层对象对应的类都必须支持深克隆。

5.使用场景

  • 创建的对象过于庞大的时候,可以通过拷贝对已有的对象进行拷贝,提高效率;
  • 如果系统要保存对象的状态,做备用的时候可以使用拷贝,留存。

总结

以上就是今天要讲的内容,本文介绍了原型模式的组成,实现和使用场景,并提供代码示例。


http://www.ppmy.cn/ops/42784.html

相关文章

C# 针对DPI和像素、毫米、英寸互相转换

在C#中&#xff0c;要进行DPI&#xff08;每英寸点数&#xff09;、像素、毫米、英寸之间的转换&#xff0c;通常需要知道屏幕或设备的DPI值。 展示如何在已知DPI的情况下进行这些单位的相互转换&#xff0c;示例代码。 获取屏幕DPI 首先&#xff0c;获取屏幕的DPI&#xff…

LabVIEW虚拟测试实验室开发

LabVIEW虚拟测试实验室开发 在当代的科技和工业进步中&#xff0c;测试与测量扮演着至关重要的角色。随着技术的发展&#xff0c;测试系统也变得日益复杂和成本昂贵&#xff0c;同时对测试结果的准确性和测试过程的效率要求越来越高。开发了一种基于LabVIEW的虚拟测试实验室的…

安卓开发:相机水印设置

1.更新水印 DecimalFormat DF new DecimalFormat("#"); DecimalFormat DF1 new DecimalFormat("#.#");LocationManager LM (LocationManager)getSystemService(Context.LOCATION_SERVICE); LM.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2…

【限免】杂波环境下线性调频脉冲、巴克码、频率步进脉冲雷达MTI、脉冲压缩【附MATLAB代码】

来源&#xff1a;微信公众号&#xff1a;EW Frontier 本代码主要模拟杂波环境&#xff08;飞机、地杂波、鸟类信号&#xff09;下&#xff0c;Chirp脉冲、巴克码脉冲、频率步进脉冲雷达信号的脉冲压缩及MTI、​匹配滤波。 MATLAB主代码 % 定义参数 fs 1000; % 采样率 T 1; …

LLVM Visual Studio构建

cd llvm-project-main cmake -S llvm -B build -G "Visual Studio 16 2019" -DLLVM_ENABLE_PROJECTSclang-tools-extra -DLLVM_ENABLE_PROJECTSclang .

QGraphicsView中鼠标位置图像缩放时不变

设置QGraphicsView的变换锚和调整尺寸锚到鼠标下面的操作&#xff0c;是一个很常见的模式&#xff0c;尤其在实现图形视图的缩放和滚动功能时。这两行代码的作用是提高用户与图形界面交互的直观性和效率。 setTransformationAnchor(QGraphicsView::AnchorUnderMouse)&#xff1…

MATLAB增强型鲸鱼优化改进算法代码复现实例

MATLAB增强型鲸鱼优化改进算法代码复现实例 MATLAB增强型鲸鱼优化改进算法代码复现实例

前端自定义滚动条样式

/* 滚动条轨道 */ ::-webkit-scrollbar-track {background-color: #f1f1f1; /* 轨道背景色 */ }/* 滚动条滑块 */ ::-webkit-scrollbar-thumb {background-color: #888; /* 滑块颜色 */border-radius: 5px; /* 滑块圆角 */ }/* 鼠标悬停在滑块上的效果 */ ::-webkit-scrollbar-…