【Java 设计模式】创建者模式 之原型模式
创始人
2024-02-19 17:47:33
0

原型模式

  • §1 定义
  • §2 角色
  • §3 三好学生案例
    • §3.1 浅克隆实现
      • §3.1.1 浅克隆定义
      • §3.1.2 类图
      • §3.1.3 实现
    • §3.2 深克隆实现
      • §3.2.1 深克隆定义
      • §3.2.2 实现

§1 定义

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

§2 角色

  • 抽象原型类:定义具体原型类需要实现的 clone 方法,对于 Java 来说,具体原型类直接实现 Cloneable 接口重写 clone 方法即可,无需再重新定义抽象原型类。
  • 具体原型类:实现抽象原型类的 clone 方法。
  • 访问类:使用具体原型类中的 clone 方法复制新对象。

§3 三好学生案例

  • 班级里有多名同学获得了三好学生的奖状,除了奖状上的获奖人姓名不一样外,其他都是一样的,使用原型模式复制出多个三好学生奖状,然后修改奖状上的名字。

§3.1 浅克隆实现

§3.1.1 浅克隆定义

  • 创建一个新的对象,新对象的属性和原型对象的完全相同,对于非基本类型的属性,仍然指向原型对象所指向的对象的内存地址

§3.1.2 类图

在这里插入图片描述

§3.1.3 实现

// 具体原型类: 奖状
public class Citation implements Cloneable {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void show() {System.out.println("三好学生:" + name);}@Overrideprotected 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 Student {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}// 具体原型类: 奖状
public class Citation implements Cloneable {private Student student;public Student getStudent() {return student;}public void setStudent(Student student) {this.student = student;}public void show() {System.out.println("三好学生:" + student.getName());}@Overrideprotected Citation clone() throws CloneNotSupportedException {return (Citation) super.clone();}
}// 访问类
public class CitationTest {public static void main(String[] args) throws CloneNotSupportedException {Citation c1 = new Citation();Student student1 = new Student();student1.setName("张三");c1.setStudent(student1);Citation c2 = c1.clone();Student student2 = c2.getStudent();student2.setName("李四");System.out.println("student1和student2是同一个对象吗?" + (student1 == student2));c1.show();c2.show();}
}
/* 输出结果:
student1和student2是同一个对象吗?true
三好学生:李四
三好学生:李四
*/
  • 测试结果可以看出,两个 student 对象是同一个对象,当修改克隆后的学生名字时,原型对象的名字也被修改了,这是浅克隆方式的弊端。可以使用深克隆方式解决。

§3.2 深克隆实现

§3.2.1 深克隆定义

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

§3.2.2 实现

// 学生类
public class Student implements Serializable {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}// 具体原型类: 奖状
public class Citation implements Cloneable, Serializable {private Student student;public Student getStudent() {return student;}public void setStudent(Student student) {this.student = student;}public void show() {System.out.println("三好学生:" + student.getName());}@Overrideprotected Citation clone() throws CloneNotSupportedException {return (Citation) super.clone();}
}// 访问类
public class CitationTest {public static void main(String[] args) throws Exception {Citation c1 = new Citation();Student student1 = new Student();student1.setName("张三");c1.setStudent(student1);ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\study\\a.txt"));oos.writeObject(c1);oos.close();ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\study\\a.txt"));Citation c2 = (Citation) ois.readObject();ois.close();Student student2 = c2.getStudent();student2.setName("李四");System.out.println("student1和student2是同一个对象吗?" + (student1 == student2));c1.show();c2.show();}
}
/* 输出结果:
student1和student2是同一个对象吗?false
三好学生:张三
三好学生:李四
*/
  • 使用序列化和反序列化的方式实现深克隆,解决浅克隆的弊端。

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...