详解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技术站