本文共 2764 字,大约阅读时间需要 9 分钟。
Prototype原型模式
是一种创建型设计模式,它允许一个对象再创建另外一个可定制的对象。
Java Object中已经提供了一个Clone( )方法,但是要实现原型模式,必须实现Cloneable接口,使用Cloneable接口都不用导入包。
克隆一个对象有两种方式:
浅克隆:copy该对象,然后保留该对象原有的引用。也就是说不克隆该对象的属性。
深克隆:copy该对象,并且把该对象的所有属性也克隆出一份新的。
我们先看一下如下代码的运行结果:
public class School { private String name; private String type; public School(String name, String type){ this.name = name; this.type = type; } /*构造方法、get方法、set方法省略*/}
public class Student implements Cloneable { private String name; private int age; private School school; /*构造方法、get方法、set方法省略*/ @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
public class Prototype { public static void main(String[] args){ School school = new School("AAA","Junior High"); Student studentA = new Student("alex", 0, school); System.out.println(studentA.toString()); try { Student studentB = (Student) studentA.clone(); System.out.println(studentB.toString()); System.out.println("======================"); school.setName("BBB"); school.setType("Senior High"); studentA.setName("Jack"); studentA.setAge(10); System.out.println(studentA.toString()); System.out.println(studentB.toString()); }catch (CloneNotSupportedException e){ e.printStackTrace(); } }}
运行结果:
上图的运行结果中,感觉部分属性复制成功(红色字段),部分属性没有复制成功(绿色字段),这是什么原因呢?
我们需要来了解clone()主要做了些什么,创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。因此,原始对象及其副本引用同一个对象。
也就是说Student的内部属性中包含有两个引用类型,因此即便使用clone方法,原始对象及其副本引用同一个对象。
那这么实现完全的复制呢,也就是深克隆呢?
一个简单直接的想法就是在克隆对象的同时,把该对象的属性也连带着克隆出新的。 这就要求这个被引用的对象必须也要实现Cloneable接口并且实现clone方法。其实此法也是换汤不换药,那有没有更好一点的方法呢?有的,这就是序列化与反序列化
。
public class School implements Serializable{ private String name; private String type; public School(String name, String type){ this.name = name; this.type = type; }}
public class Student implements Serializable { private String name; private int age; private School school; public Student(String name, int age, School school){ this.name = name; this.age = age; this.school = school; /*构造方法、get方法、set方法省略*/ protected Object deepClone() throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); }}
可以看到,对象被完全复制了。
本文介绍了原型模式,并以此引出了浅拷贝和深拷贝两种对象复制方式,希望能对读者有所帮助。