定义:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.
Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建
浅复制
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其对象的引用都仍然指向原来的对象。
Java的java.lang.Object方法里就提供了克隆方法clone(),原则上似乎所有类都拥有此功能,但其实不然,关于它的使用有如下限制:
1、要实现克隆,必须实现java.lang.Cloneable接口,否则在运行时调用clone()方法,会抛CloneNotSupportedException异常。
2、返回的是Object类型的对象,所以使用时可能需要强制类型转换。
3、该方法是protected的,如果想让外部对象使用它,必须在子类重写该方法,设定其访问范围是public的,参见PackageInfo的clone()方法。
4、Object的clone()方法的复制是采用逐字节的方式从复制内存数据,复制了属性的引用,而属性所指向的对象本身没有被复制,因此所复制的引用指向了相同的对象。由此可见,这种方式拷贝对象是浅拷贝,不是深拷贝。
即复制的对象跟源对象是不同的对象,但若源对象里包括其他对象引用,则新对象里复制的也是那个其他对象引用,而非其他对象的新对象。
package testPackage; import java.util.Date; public class Mokey implements Cloneable { private int height; private int weight; private Date birthDate; private GoldRingdeStaff goldRingdeStaff; public Mokey() { birthDate = new Date(); } public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public Object clone() { Mokey mokey = null; try { mokey = (Mokey) super.clone(); } catch (CloneNotSupportedException e) { // TODO 自动生成 catch 块 e.printStackTrace(); } finally { return mokey; } } public GoldRingdeStaff getGoldRingdeStaff() { return goldRingdeStaff; } public void setGoldRingdeStaff(GoldRingdeStaff goldRingdeStaff) { this.goldRingdeStaff = goldRingdeStaff; } }
package testPackage; public class GoldRingdeStaff { private float height = 100.0f; private float weight = 10.0f; public float getHeight() { return height; } public void setHeight(float height) { this.height = height; } public float getWeight() { return weight; } public void setWeight(float weight) { this.weight = weight; } }
package testPackage; public class TestPrototype { private Mokey mokey= new Mokey(); public void change() { Mokey copymokey2; copymokey2 = (Mokey) mokey.clone(); System.out.println("monkey birth date :" + mokey.getBirthDate()); System.out.println("copymokey2 birth date :"+ copymokey2.getBirthDate()); System.out.println("copymokey2 ==monkey :" + (copymokey2 == mokey)); System.out.println("copymokey2 staff ==monkey staff:" + (copymokey2.getGoldRingdeStaff() == mokey.getGoldRingdeStaff())); } public static void main(String[] args) { TestPrototype t = new TestPrototype(); t.change(); } }
结果:
monkey birth date :Mon Jul 09 17:25:38 CST 2012
copymokey2 birth date :Mon Jul 09 17:25:38 CST 2012
copymokey2 ==monkey :false
copymokey2 staff ==monkey staff:true
深复制
被复制对象的所有的变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把重复的对象所引用的对象都复制一遍,而这种对被引用到的对象的复制叫做间接复制。
通过上述学习,我们知道Java提供了浅拷贝的方法,那么,如何实现一个深拷贝呢?一般情况下,我们有两种方式来实现:
1. 拷贝对象时,递归地调用属性对象的克隆方法完成。读者可以根据具体的类,撰写出实现特定类型的深拷贝方法。
一般地,我们很难实现一个一般性的方法来完成任何类型对象的深拷贝。有人根据反射得到属性的类型,然后依照它的类型构造对象,但前提是,这些属性的类型必须含有一个公有的默认构造方法,否则作为一个一般性的方法,很难确定传递给非默认构造方法的参数值;此外,如果属性类型是接口或者抽象类型,必须提供查找到相关的具体类方法,作为一个一般性的方法,这个也很难办到。
2. 如果类实现了java.io.Serializable接口,把原型对象序列化,然后反序列化后得到的对象,其实就是一个新的深拷贝对象。
public Object deepClone() throws IOException, ClassNotFoundException { ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo= new ObjectOutputStream(bo); oo.writeObject(this); ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi= new ObjectInputStream(bi); return (oi.readObject()); }
来源:http://blog.sina.com.cn/s/blog_563742da0100bkep.html
http://www.iteye.com/topic/1045580