原型模式:prototype模式

定义:

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 


Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建


浅复制

   被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。


 

Java的java.lang.Object方法里就提供了克隆方法clone(),原则上似乎所有类都拥有此功能,但其实不然,关于它的使用有如下限制:

1、要实现克隆,必须实现java.lang.Cloneable接口,否则在运行时调用clone()方法,会抛CloneNotSupportedException异常。

2、返回的是Object类型的对象,所以使用时可能需要强制类型转换。

3、该方法是protected的,如果想让外部对象使用它,必须在子类重写该方法,设定其访问范围是public的,参见PackageInfo的clone()方法。

4、Object的clone()方法的复制是采用逐字节的方式从复制内存数据,复制了属性的引用,而属性所指向的对象本身没有被复制,因此所复制的引用指向了相同的对象。由此可见,这种方式拷贝对象是浅拷贝,不是深拷贝。

Java代码   收藏代码
  1. package testPackage;  
  2.   
  3. import java.util.Date;  
  4.   
  5. public class Mokey implements Cloneable {  
  6.   
  7.     private int height;  
  8.     private int weight;  
  9.     private Date birthDate;  
  10.     private GoldRingdeStaff goldRingdeStaff;  
  11.   
  12.     public Mokey() {  
  13.         birthDate = new Date();  
  14.     }  
  15.   
  16.     public Date getBirthDate() {  
  17.         return birthDate;  
  18.     }  
  19.   
  20.     public void setBirthDate(Date birthDate) {  
  21.         this.birthDate = birthDate;  
  22.     }  
  23.   
  24.     public int getHeight() {  
  25.         return height;  
  26.     }  
  27.   
  28.     public void setHeight(int height) {  
  29.         this.height = height;  
  30.     }  
  31.   
  32.     public int getWeight() {  
  33.         return weight;  
  34.     }  
  35.   
  36.     public void setWeight(int weight) {  
  37.         this.weight = weight;  
  38.     }  
  39.   
  40.     public Object clone() {  
  41.         Mokey mokey = null;  
  42.         try {  
  43.             mokey = (Mokey) super.clone();  
  44.         } catch (CloneNotSupportedException e) {  
  45.             // TODO 自动生成 catch 块  
  46.             e.printStackTrace();  
  47.         } finally {  
  48.             return mokey;  
  49.         }  
  50.     }  
  51.   
  52.     public GoldRingdeStaff getGoldRingdeStaff() {  
  53.         return goldRingdeStaff;  
  54.     }  
  55.   
  56.     public void setGoldRingdeStaff(GoldRingdeStaff goldRingdeStaff) {  
  57.         this.goldRingdeStaff = goldRingdeStaff;  
  58.     }  
  59.   
  60. }  
  
Java代码   收藏代码
  1. package testPackage;  
  2.   
  3. public class GoldRingdeStaff {  
  4.     private float height = 100.0f;  
  5.     private float weight = 10.0f;  
  6.   
  7.     public float getHeight() {  
  8.         return height;  
  9.     }  
  10.   
  11.     public void setHeight(float height) {  
  12.         this.height = height;  
  13.     }  
  14.   
  15.     public float getWeight() {  
  16.         return weight;  
  17.     }  
  18.   
  19.     public void setWeight(float weight) {  
  20.         this.weight = weight;  
  21.     }  
  22.   
  23. }  
 

 

 

Java代码   收藏代码
  1. package testPackage;  
  2.   
  3. public class TestPrototype {  
  4.   
  5.     private Mokey mokey= new Mokey();  
  6.       
  7.     public void change() {  
  8.         Mokey copymokey2;  
  9.         copymokey2 = (Mokey) mokey.clone();  
  10.         System.out.println("monkey birth date :" + mokey.getBirthDate());  
  11.         System.out.println("copymokey2 birth date :"+ copymokey2.getBirthDate());  
  12.         System.out.println("copymokey2 ==monkey :" + (copymokey2 == mokey));  
  13.         System.out.println("copymokey2 staff ==monkey staff:"  
  14.                 + (copymokey2.getGoldRingdeStaff() == mokey.getGoldRingdeStaff()));  
  15.     }  
  16.   
  17.     public static void main(String[] args) {  
  18.         TestPrototype t = new TestPrototype();  
  19.         t.change();  
  20.     }  
  21.   
  22. }  

结果:

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接口,把原型对象序列化,然后反序列化后得到的对象,其实就是一个新的深拷贝对象。


Java代码   收藏代码
  1. public Object deepClone() throws IOException, ClassNotFoundException {  
  2.           ByteArrayOutputStream bo = new ByteArrayOutputStream();  
  3.           ObjectOutputStream oo= new ObjectOutputStream(bo);  
  4.           oo.writeObject(this);  
  5.             
  6.           ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());  
  7.           ObjectInputStream oi= new ObjectInputStream(bi);  
  8.           return (oi.readObject());  
  9.     } 
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页