详解JAVA 原型模式

yizhihongxing

详解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程序生成Access文件代码实例

    下面我来详细讲解“Java程序生成Access文件代码实例”的完整攻略。 1. 确定操作需求 首先,我们要确定自己的操作需求。需要生成Access文件的具体表结构和数据要素是什么?这一环节是至关重要的,要确保对表结构和数据元素有清晰的把握。 2. 加载JDBC驱动 准备工作之后,我们需要加载JDBC驱动,以便向Access数据库发出连接请求。下面是使用JDB…

    Java 2023年5月20日
    00
  • 使用 Apache 反向代理的设置技巧

    下面我将为大家详细介绍使用 Apache 反向代理的设置技巧的完整攻略。 一、反向代理的基本概念 反向代理是一种代理模式,其代理对象不是客户端,而是服务端。它可以将多个 web 服务器虚拟为一个地址,以便统一代理。客户端访问这个地址,由反向代理服务器将请求转发到真正的服务器上去,并将响应返回给客户端。 反向代理的优点包括:- 可以在前端部署负载均衡;- 可以…

    Java 2023年6月2日
    00
  • Springboot内嵌tomcat应用原理深入分析

    Spring Boot是现今最流行的Java Web框架之一,其最大的优点是使用内嵌的Tomcat容器,降低了Web应用的开发和部署成本。本文将深入分析Spring Boot内嵌Tomcat应用的原理,并介绍两个示例。 1. Spring Boot内嵌Tomcat原理 Spring Boot应用的内嵌Tomcat配置在pom.xml文件中的依赖中引入了Tom…

    Java 2023年5月19日
    00
  • 29基于java的在线考试系统设计与实现

    本章节来介绍一个基于java的在线考试系统的实现 系统概要 近年来,随着世界各国需要参加考核的人员与日俱增,单纯依靠传统的人工安排考场和监考人员的纸质化考试逐渐显示出了效率低,易发生冲突的缺陷,这时,在线考试系统便应运而生,此种考试方式以方便快捷高效等优点将越来越适用于如今的各项考试、考核。此外,无纸化在线考试对考试人员和审阅人员均提供了便捷。因此,本文将主…

    Java 2023年5月8日
    00
  • Java的Struts框架报错“TokenExpiredException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“TokenExpiredException”错误。这个错误通常由以下原因之一起: 令牌过期:如果令牌过期,则可能会出现此错误。在这种情况下,需要重新生成令牌以解决此问题。 配置错误:如果配置文件中没有正确配置,则可能会出现此错误。在这种情况下,需要检查文件以解决此问题。 以下是两个实例: 例 1 如果令牌过期,…

    Java 2023年5月5日
    00
  • Java 随机取字符串的工具类

    接下来我将为你讲解如何实现“Java 随机取字符串的工具类”,具体步骤如下: 1. 定义工具类 首先,在Java项目中,你需要定义一个名为StringRandomUtils的工具类,该类的作用是提供随机字符串相关的方法。 public class StringRandomUtils { } 2. 实现随机生成字符串的方法 在定义完工具类之后,你需要实现随机生…

    Java 2023年5月27日
    00
  • 软引用的作用是什么?

    软引用是Java语言中的一种引用类型,用于描述一些有用但不必须的对象。在Java中,垃圾回收器在回收时会自动处理所有的软引用对象,但只有在内存空间不足时才会回收这些对象。 使用软引用可以解决一些问题,如内存泄漏、内存占用等问题。下面介绍软引用的使用攻略: 1. 创建软引用对象 在Java中,可以使用java.lang.ref.SoftReference类来创…

    Java 2023年5月10日
    00
  • Java中的SecurityException是什么?

    Java中的SecurityException是一种运行时异常,表示安全限制被违反。当Java应用程序试图执行需要更高级别权限才能执行的操作时,就会抛出SecurityException异常。例如,如果Java应用程序运行在沙箱中,将尝试访问本地文件系统或网络时,就会抛出SecurityException异常。 通常情况下,SecurityException…

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