原型模式(Prototype Pattern):使用原型實例指定建立對象的種類,而且經過拷貝這些原型建立新的對象。原型模式是一種對象建立型模式。git
原型模式的工做原理很簡單:將一個原型對象傳給那個要發動建立的對象,這個要發動建立的對象經過請求原型對象拷貝本身來實現建立過程。因爲在軟件系統中咱們常常會遇到須要建立多個相同或者類似對象的狀況,所以原型模式在真實開發中的使用頻率仍是很是高的。原型模式是一種「另類」的建立型模式,建立克隆對象的工廠就是原型類自身,工廠方法由克隆方法來實現。編程
須要注意的是經過克隆方法所建立的對象是全新的對象,它們在內存中擁有新的地址,一般對克隆所產生的對象進行修改對原型對象不會形成任何影響,每個克隆對象都是相互獨立的。經過不一樣的方式修改能夠獲得一系列類似但不徹底相同的對象。結構如圖:設計模式
在原型模式結構圖中包含以下幾個角色:ide
1 對象的克隆方法函數
通用的克隆實現方法是在具體原型類的克隆方法中實例化一個與自身類型相同的對象並將其返回,並將相關的參數傳入新建立的對象中,保證它們的成員屬性相同。代碼以下:ui
public class ConcretePrototype implements Prototype { private String attr; public String getAttr() { return attr; } public void setAttr(String attr) { this.attr = attr; } @Override public Prototype clone() { ConcretePrototype concretePrototype = new ConcretePrototype(); concretePrototype.setAttr(this.attr); return concretePrototype; } }
代碼以下:this
class ConcretePrototype2 implements Cloneable { @Override public Prototype clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return (Prototype) object; } }
2 淺克隆與深克隆的實現,代碼以下:設計
public class WeeklyLog implements Cloneable,Serializable { private static final long serialVersionUID = 8532521622598526741L; private String name; private String content; private Attachment attachment; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Attachment getAttachment() { return attachment; } public void setAttachment(Attachment attachment) { this.attachment = attachment; } @Override //淺克隆,克隆出來的對象中的Attachment指向同一個對象地址 public WeeklyLog clone(){ Object obj; try { obj = super.clone(); return (WeeklyLog)obj; } catch(CloneNotSupportedException e) { System.out.println("不支持複製!"); return null; } } //深克隆,克隆出來的對象中的Attachment爲不一樣的對象 public WeeklyLog deepClone() throws IOException, ClassNotFoundException { //將對象寫入流中 ByteArrayOutputStream bao=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bao); oos.writeObject(this); //將對象從流中取出 ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray()); ObjectInputStream ois=new ObjectInputStream(bis); return (WeeklyLog)ois.readObject(); } } class Attachment { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Java語言提供的Cloneable接口和Serializable接口的代碼很是簡單,它們都是空接口,做爲一種標識,本質上是調用的Object類的方法code
3 利用原型模式可實現一個原型管理器,專門負責克隆相應的對應,代碼以下:
public class PrototypeManager { private static PrototypeManager instance = new PrototypeManager(); private Map<String, OfficialDocument> hm = new ConcurrentHashMap<>(); private PrototypeManager() { hm.put("far", new FAR()); hm.put("srs", new SRS()); } public PrototypeManager getInstance() { return instance; } //增長新的公文對象 public void addOfficialDocument(String key, OfficialDocument doc) { hm.put(key, doc); } //經過淺克隆獲取新的公文對象 public OfficialDocument getOfficialDocument(String key) { return ((OfficialDocument) hm.get(key)).clone(); } } //抽象公文接口,也可定義爲抽象類,提供clone()方法的實現,將業務方法聲明爲抽象方法 interface OfficialDocument extends Cloneable { OfficialDocument clone(); void display(); } //可行性分析報告(Feasibility Analysis Report)類 class FAR implements OfficialDocument { @Override public OfficialDocument clone() { OfficialDocument far = null; try { far = (OfficialDocument) super.clone(); } catch (CloneNotSupportedException e) { System.out.println("不支持複製!"); } return far; } @Override public void display() { System.out.println("《可行性分析報告》"); } } //軟件需求規格說明書(Software Requirements Specification)類 class SRS implements OfficialDocument { @Override public OfficialDocument clone() { OfficialDocument srs = null; try { srs = (OfficialDocument) super.clone(); } catch (CloneNotSupportedException e) { System.out.println("不支持複製!"); } return srs; } @Override public void display() { System.out.println("《軟件需求規格說明書》"); } }
用來複制一個對象,無需知道具體建立過程,可進行對象的淺克隆或深克隆。