一.原型模式的概念

  1. 原型模式(Prototype Pattern)指使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。原型模式本身没有太多可说的内容,接下来更多的着眼于如何在java中做浅拷贝和深拷贝。

二.浅拷贝

  1. 浅拷贝指在复制时把成员类型中基本数据类型复制一份给新对象,但成员类型中引用类型只会复制地址给新对象(也就是说引用类型的成员在复制后被新旧对象所共用)。实现浅拷贝的一种优雅的方式是继承javaCloneale接口,然后使用Object类自带的clone()方法,代码如下:
  1. public class Prototype implements Cloneable{
  2. public Prototype clone(){
  3. Object object = null;
  4. try{
  5. object = super.clone();
  6. }catch(CloneNotSupportedException e){
  7. e.printTrace();
  8. }
  9. return (Prototype)object;
  10. }
  11. }
  1. 同时也可以通过定义Prototype为参数的构造方法来实现拷贝,比较简单就不列代码了。

三.深拷贝

  1. 深拷贝主要目的在于把引用类型的成员变量也复制一份给新对象。我们可以通过重写原型类及其所有成员类的clone()方法来实现深拷贝。

成员类:

  1. public class Property implements Cloneable{
  2. public Property clone(){
  3. Object object = null;
  4. try{
  5. object = super.clone();
  6. }catch(CloneNotSupportedException e){
  7. e.printTrace();
  8. }
  9. return (Property)object;
  10. }
  11. }

原型类:

  1. public class Prototype implements Cloneable{
  2. Property property;
  3. //...set and get
  4. public Prototype clone(){
  5. Object object = null;
  6. try{
  7. object = super.clone();
  8. }catch(CloneNotSupportedException e){
  9. e.printTrace();
  10. }
  11. Prototype p = (Prototype)object;
  12. p.property=p.getProperty().clone();
  13. retutn p;
  14. }
  15. }
  1. 这种方式需要实现所有相关类的clone()方法,稍显麻烦,java中更常用的深拷贝方式是通过**序列化**。首先让相关类继承Serializable接口。<br />
  1. public class Property implements Serializable{
  2. }
  3. public class Prototype implements Serializable{
  4. Property property;
  5. //...
  6. }


把类转化成二进制字节码,之后通过读取这个字节码就可以拷贝原对象。

  1. public class DeepCopyBySerialization {
  2. public static void main(String[] args) throws IOException, ClassNotFoundException {
  3. Prototype p1=new Prototype();
  4. //通过序列化方法实现深拷贝
  5. ByteArrayOutputStream bos=new ByteArrayOutputStream();
  6. ObjectOutputStream oos=new ObjectOutputStream(bos);
  7. oos.writeObject(p);
  8. oos.flush();
  9. ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
  10. Prototype p2=(Prototype)ois.readObject();
  11. }
  12. }
  1. 对于不想被序列化的成员可以用transient修饰。