详解JAVA 原型模式

详解JAVA 原型模式

什么是原型模式?

原型模式(Prototype Pattern),又叫克隆模式,是指通过复制已经存在的一个对象生成一个新的对象,新的对象是通过对原始对象进行复制而生成的,原始对象就可以充当新对象的一个原型。原型模式是一种创建型模式,其作用是通过把一个实例作为原型,复制出新的实例来。

原型模式的使用场景

  • 在需要创建对象的过程中,如果创建新的对象的代价比较大,而且我们已经有了一个相同对象可以直接复制,则可以使用原型模式来避免重复创建对象,以提高创建对象的效率。
  • 在需要重新组合一个对象时,如果对象内部结构比较复杂或者对象之间的相互依赖关系比较难以处理,那么可以使用原型模式来方便重新组合一个新的对象。

JAVA 实现原型模式

JAVA 实现原型模式一般需要满足以下两个条件:

  • 实现 Cloneable 接口
  • 使用 clone() 方法

实现 Cloneable 接口

Cloneable 是一个标记接口,用于表明一个类可以被复制。如果我们没有实现该接口,调用 clone() 方法会抛出 CloneNotSupportedException 异常。

使用 clone() 方法

JAVA 中的 clone() 方法是一个 protected 的方法,我们需要在自己的类中重写这个方法并将它的访问修饰符改为 public。另外,在 clone() 方法中,我们需要使用 super.clone() 方法。因为 Object 类中的 clone() 方法会为新对象分配内存,并将原始对象的值复制到新对象中。

JAVA 原型模式示例

下面通过一个示例来演示如何使用 JAVA 原型模式。

示例1:复制简单对象

假设我们有一个学生对象(Student),它有两个属性:name 和 age。我们使用原型模式来创建一个新的学生对象。

public class Student implements Cloneable {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

上面的代码中,我们实现了 Cloneable 接口,并重写了 clone() 方法。在 clone() 方法中,我们使用 super.clone() 方法来创建新的学生对象。然后在使用 clone() 方法创建新的学生对象时,只需要调用原始对象的 clone() 方法即可。

示例代码如下:

public class PrototypeDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student("Tom", 18);
        System.out.println("student1 = " + student1);

        Student student2 = (Student) student1.clone();
        System.out.println("student2 = " + student2);

        student2.setName("Jerry");
        student2.setAge(20);

        System.out.println("student1 = " + student1);
        System.out.println("student2 = " + student2);
    }
}

示例2:复制包含对象的对象

现在,我们来看一个更加复杂的示例。假设我们有一个学生对象(Student),它包含一个班级对象(Classroom),班级对象又包含多个学生对象。我们现在想要复制一个新的学生对象,它的班级和班级中的学生对象也需要被复制。

public class Student implements Cloneable {
    private String name;
    private int age;
    private Classroom classroom;

    public Student(String name, int age, Classroom classroom) {
        this.name = name;
        this.age = age;
        this.classroom = classroom;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setClassroom(Classroom classroom) {
        this.classroom = classroom;
    }

    public Classroom getClassroom() {
        return classroom;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Student student = (Student) super.clone();
        student.classroom = (Classroom) student.classroom.clone();
        return student;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", classroom=" + classroom +
                '}';
    }
}

public class Classroom implements Cloneable {
    private String className;
    private List<Student> students;

    public Classroom(String className, List<Student> students) {
        this.className = className;
        this.students = students;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getClassName() {
        return className;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    public List<Student> getStudents() {
        return students;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Classroom classroom = (Classroom) super.clone();

        List<Student> students = new ArrayList<>();
        for (Student student : classroom.getStudents()) {
            students.add((Student) student.clone());
        }
        classroom.setStudents(students);

        return classroom;
    }

    @Override
    public String toString() {
        return "Classroom{" +
                "className='" + className + '\'' +
                ", students=" + students +
                '}';
    }
}

上面的代码中,我们在 Student 类和 Classroom 类中都实现了 Cloneable 接口,并重写了 clone() 方法。在 Student 类的 clone() 方法中,我们使用 super.clone() 方法创建新的学生对象,并将班级对象也进行复制。在 Classroom 类的 clone() 方法中,我们首先通过 super.clone() 方法创建新的班级对象,然后再复制班级中的所有学生对象。

示例代码如下:

public class PrototypeDemo2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student("Tom", 18, new Classroom("ClassA", Arrays.asList(new Student("Jerry", 20, null))));
        System.out.println("student1 = " + student1);

        Student student2 = (Student) student1.clone();
        System.out.println("student2 = " + student2);

        student2.getClassroom().getStudents().get(0).setName("Jack");
        student2.getClassroom().getStudents().get(0).setAge(22);

        System.out.println("student1 = " + student1);
        System.out.println("student2 = " + student2);
    }
}

运行上述代码后,我们可以看到新创建的学生对象和班级对象都和原始对象不同,已经成功地实现了对象的深度复制。

总结

原型模式是设计模式中的一种,它可以避免重复创建对象,提高创建对象的效率。JAVA 中的原型模式需要实现 Cloneable 接口,并重写 clone() 方法。如果一个对象包含其他对象,则需要对其进行深度复制。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解JAVA 原型模式 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Java实现读取键盘输入保存到txt文件,再统计并输出每个单词出现次数的方法

    首先,我们需要了解如何从键盘读取输入并保存到txt文件中,接着再通过编程实现统计每个单词出现次数。下面是完整攻略: 1. 从键盘读取输入并保存到txt文件中 我们可以使用Scanner类从键盘获取用户输入,将输入的内容保存到txt文件中。代码如下: import java.io.*; public class Main { public static voi…

    Java 2023年5月26日
    00
  • JAVA对象和字节数组互转操作

    Java对象和字节数组互转操作是Java编程中常见的技巧之一。在某些情况下,我们需要把Java对象序列化成字节数组,再把字节数组反序列化为Java对象,这样可以在网络传输、文件存储等场景中实现数据的传输和存储。本文以Java 8为例,讲解Java对象和字节数组互转的完整攻略。 1. Java对象转字节数组 Java对象转字节数组需要使用到Java的序列化机制…

    Java 2023年5月26日
    00
  • 微信小程序模板template简单用法示例

    微信小程序模板template简单用法示例 什么是小程序模板? 小程序模板是一种可复用的代码结构,可以在多个页面中使用。它包含了一些 HTML、CSS、JavaScript 代码,用于渲染页面元素。 如何使用小程序模板? 在微信小程序中,使用小程序模板需要遵循以下步骤: 在 *.wxml 文件中引入模板:使用 wxml 标签的 import 属性,将需要引入…

    Java 2023年5月23日
    00
  • 什么是GC日志?

    GC日志是指GC(Garbage Collection,垃圾回收)的记录日志,主要用于排查JVM内存问题和性能调优。在GC发生时,JVM会记录下当前内存使用情况、GC时间、GC原因、GC类型、GC前后各个内存区域的使用情况等信息,并输出到GC日志中。 常见的GC日志有以下几种格式: -Xloggc:filename [可简写为 -verbose:gc,从JD…

    Java 2023年5月11日
    00
  • SpringBoot整合spring-data-jpa的方法

    下面是关于Spring Boot整合spring-data-jpa的方法的详细攻略: 1. 引入依赖 在pom.xml文件中,增加以下两个依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-st…

    Java 2023年5月20日
    00
  • 通过Java实现添加或删除PDF中的附件

    这里介绍通过Java实现添加或删除PDF中的附件的完整攻略: 1. 添加附件 1.1 引入相关库 import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import org.apache…

    Java 2023年5月19日
    00
  • spring boot项目如何采用war在tomcat容器中运行

    下面是Spring Boot项目如何部署到Tomcat容器中运行的攻略: 一、将项目打成war包 Spring Boot项目通常打成jar包,但是要部署到Tomcat容器中需要将其打成war包。如果使用Maven构建项目,则只需在pom.xml文件中添加以下代码: <packaging>war</packaging> 这样项目就会被打…

    Java 2023年6月2日
    00
  • 如何使用java写Student类的功能

    下面详细讲解如何使用Java写Student类的功能的完整攻略,过程中包含两条示例说明。 1. 定义Student类 首先,我们需要定义一个Student类,代码如下: public class Student { private String name; private int age; public Student(String name, int ag…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部