概念:
原形模式:
原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.
原型模式中的拷贝分为"浅拷贝"和"深拷贝":
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.
演示:
package com.dairuijie.prototype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * 原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个 对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对。在 Java 中,复制对象是通过 clone()实现的 实现深复制需要实现Serializable 可以序列化 不然没法序列化对象去进行流的输入输出 * @author DRJYY * */ public class Prototype implements Cloneable,Serializable{ /** * */ private static final long serialVersionUID = 1L; private Integer age; private String name; public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } /** * 浅复制 */ @Override protected Object clone() throws CloneNotSupportedException { /* Prototype prot = (Prototype) super.clone(); return prot;*/ return super.clone(); } /** * 深复制 * @return * @throws IOException * @throws ClassNotFoundException */ public 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; ois = new ObjectInputStream(bis); return ois.readObject(); } public Prototype(Integer age, String name) { this.age = age; this.name = name; } }
package com.dairuijie.prototype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * 学生实体类 除了基本数据类型 同时包括Prototype 引用 方便我们测试结果 * @author DRJYY * */ public class Student implements Cloneable,Serializable{ /** * */ private static final long serialVersionUID = 1L; private Integer age; private String name; private Prototype prototype; public Prototype getPrototype() { return prototype; } public void setPrototype(Prototype prototype) { this.prototype = prototype; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } public Student(Integer age, String name, Prototype prototype) { this.age = age; this.name = name; this.prototype = prototype; } public 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; ois = new ObjectInputStream(bis); return ois.readObject(); } }
package com.dairuijie.prototype; import java.io.IOException; /** * * @author DRJYY * */ public class ShallowTest { public static void main(String[] args) throws ClassNotFoundException, IOException { Prototype p = new Prototype(12, "dai"); Student student = new Student(13, "dai", p); Student stu = (Student) student.deepClone(); stu.getPrototype().setAge(123); stu.setAge(11); System.out.println("原始的student的年龄----"+student.getAge()); System.out.println("克隆对象----"+stu.getAge()); System.out.println("克隆对象中的p 引用---"+stu.getPrototype().getAge()); System.err.println("p的对象原始----"+p.getAge()); } }
package com.dairuijie.prototype; public class DeepTest { public static void main(String[] args) throws CloneNotSupportedException { Prototype p = new Prototype(12, "dai"); Student student = new Student(13, "dai", p); Student stu = (Student) student.clone(); stu.getPrototype().setAge(123); stu.setAge(11); System.out.println("原始的student的年龄----"+student.getAge()); System.out.println("克隆对象----"+stu.getAge()); System.out.println("克隆对象中的p 引用---"+stu.getPrototype().getAge()); System.err.println("p的对象原始----"+p.getAge()); } }
图一 : 图二:
如图一就是浅复制结果 发现p 的对象年龄没有变化,图二深复制中p 的对象年龄却被身体stu.getPrototype().setAge(123) 改变了。说明深复制将引用对象都复制过来了。也就是对引用类型的成员变量也进行引用对象的复制。