Java設計模式四: 原型模式(Prototype Pattern)


原型模式是一種創建型設計模式,它通過復制一個已經存在的實例來返回新的實例,而不是新建實例.被復制的實例就是我們所稱的原型,這個原型是可定制的.
原型模式多用於創建復雜的或者耗時的實例, 因為這種情況下,復制一個已經存在的實例可以使程序運行更高效,或者創建值相等,只是命名不一樣的同類數據.

原型模式中的拷貝分為"淺拷貝"和"深拷貝":
淺拷貝: 對值類型的成員變量進行值的復制,對引用類型的成員變量只復制引用,不復制引用的對象.
深拷貝: 對值類型的成員變量進行值的復制,對引用類型的成員變量也進行引用對象的復制.

類圖:

實例一:淺拷貝
public class Prototype implements Cloneable {
 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Object clone() {
  try {
   return super.clone();
  } catch (CloneNotSupportedException e) {   
   e.printStackTrace();
   return null;
  }
 } 
 
}

public class TestMain {

 public static void main(String[] args) {
  testPrototype();
 }
 
 private static void testPrototype(){
  Prototype pro = new Prototype();
  pro.setName("original object");
  Prototype pro1 = (Prototype)pro.clone();
  pro.setName("changed object1");
  
  System.out.println("original object:" + pro.getName());
  System.out.println("cloned object:" + pro1.getName());
  
 }

}
結果:
original object:changed object1
cloned object:original object


實例二: 淺拷貝
public class Prototype{
 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 } 
 
}
public class NewPrototype implements Cloneable {
 
 private String id;
 
 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 private Prototype prototype;
 
 public Prototype getPrototype() {
  return prototype;
 }

 public void setPrototype(Prototype prototype) {
  this.prototype = prototype;
 }


 public Object clone(){ 
  try {
   return super.clone();
  } catch (CloneNotSupportedException e) {
   e.printStackTrace();
   return null;
  }  
 }

}
public class TestMain {

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  testPrototype();
 }
 
 private static void testPrototype(){
  Prototype pro = new Prototype();
  pro.setName("original object");
  NewPrototype newObj = new NewPrototype();
  newObj.setId("test1");
  newObj.setPrototype(pro);
  
  NewPrototype copyObj = (NewPrototype)newObj.clone();
  copyObj.setId("testCopy");
  copyObj.getPrototype().setName("changed object");
  
  System.out.println("original object id:" + newObj.getId());
  System.out.println("original object name:" + newObj.getPrototype().getName());
  
  System.out.println("cloned object id:" + copyObj.getId());
  System.out.println("cloned object name:" + copyObj.getPrototype().getName());
  
 }

}

結果:
original object id:test1
original object name:changed object
cloned object id:testCopy
cloned object name:changed object


實例三: 深拷貝
public class Prototype implements Cloneable {
 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Object clone() {
  try { 
   return super.clone();
  } catch (CloneNotSupportedException e) {   
   e.printStackTrace();
   return null;
  }
 } 
 
}

public class NewPrototype implements Cloneable {
 
 private String id;
 
 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 private Prototype prototype;
 
 public Prototype getPrototype() {
  return prototype;
 }

 public void setPrototype(Prototype prototype) {
  this.prototype = prototype;
 }


 public Object clone(){
  NewPrototype ret = null;
  try {
   ret = (NewPrototype)super.clone();
   ret.prototype = (Prototype)this.prototype.clone();
   return ret;
  } catch (CloneNotSupportedException e) {
   e.printStackTrace();
   return null;
  }  
 }

}

public class TestMain {

 /**
  * @param args
  */
 public static void main(String[] args) {
  testDeepCopy();
 }
 
 private static void testDeepCopy(){
  Prototype pro = new Prototype();
  pro.setName("original object");
  NewPrototype newObj = new NewPrototype();
  newObj.setId("test1");
  newObj.setPrototype(pro);
  
  NewPrototype copyObj = (NewPrototype)newObj.clone();
  copyObj.setId("testCopy");
  copyObj.getPrototype().setName("changed object");
  
  System.out.println("original object id:" + newObj.getId());
  System.out.println("original object name:" + newObj.getPrototype().getName());
  
  System.out.println("cloned object id:" + copyObj.getId());
  System.out.println("cloned object name:" + copyObj.getPrototype().getName());
  
 }

}

結果:
original object id:test1
original object name:original object
cloned object id:testCopy
cloned object name:changed object

實例四: 利用串行化來做深復制
把對象寫道流里的過程是串行化(Serilization)過程;把對象從流中讀出來是並行化(Deserialization)過程. 寫在流里的是對象的一個拷貝,然后再從流里讀出來重建對象.
public class PrototypeSe implements Serializable {

 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

}

public class NewPrototypeSe implements Serializable {
 
 private String id;
 
 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 private PrototypeSe prototype;
 
 public PrototypeSe getPrototype() {
  return prototype;
 }

 public void setPrototype(PrototypeSe prototype) {
  this.prototype = prototype;
 }
 
 public Object deepClone(){
  try {
   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(); 
  } catch (IOException | ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   return null;
  }
 }

}

public class TestDeepClone {

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  PrototypeSe po = new PrototypeSe();
  po.setName("test1");
  NewPrototypeSe se = new NewPrototypeSe();
  se.setPrototype(po);
  
  NewPrototypeSe deepClone = (NewPrototypeSe)se.deepClone();
  deepClone.getPrototype().setName("test2");
  
  System.out.println("original name:" + se.getPrototype().getName());
  System.out.println("cloned name:" + deepClone.getPrototype().getName());

 }
}
結果:
original name:test1
cloned name:test2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM