原型模式,光看字面上的意思很難了解這在幹麻,我們直接先來看正式定義及類別圖:
從定義上我們大概可以知道,這個模式的用途是讓我們可以透過複製的方式產生一個新物件。可是產生物件幹麻要這麼麻煩,不是直接 new 出一個新物件就好了嗎? 還是一句老話:有時建立物件的代價很高。假如你所需要建立的物件,其所需的資料是放在遠端資料庫的,這樣當每建立一個物件,就要讀取資料庫一次,這其實是很花成本的。
從類別圖我們可以看到,有一個公開的介面 Prototype,其子類別都需要實作 clone。而 client 這邊在取得物件時,不是透過 new 的方式,而是使用 clone() 來取得所需的物件。因此我們可以知道,此模式的重點在於 client 的程式碼可以在不知道特定類別為何的情形下可以生成新的物件。
接下來來看簡單的範例程式碼吧。在 Java 中,每個類別都繼承了 Object 這個類別,表示每個類別都含有 clone() 這個方法。但是要讓 clone() 能動,類別還必須實作 java.lang.Cloneable 這個標籤介面(Tag Interface,Marker Interface)。除了這點之外,還要注意你的 clone() 是想要淺層複製 (shallow copy) 還是深層複製 (deep copy)。
(中文好難翻譯,我不會…)
Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype.
從定義上我們大概可以知道,這個模式的用途是讓我們可以透過複製的方式產生一個新物件。可是產生物件幹麻要這麼麻煩,不是直接 new 出一個新物件就好了嗎? 還是一句老話:有時建立物件的代價很高。假如你所需要建立的物件,其所需的資料是放在遠端資料庫的,這樣當每建立一個物件,就要讀取資料庫一次,這其實是很花成本的。
從類別圖我們可以看到,有一個公開的介面 Prototype,其子類別都需要實作 clone。而 client 這邊在取得物件時,不是透過 new 的方式,而是使用 clone() 來取得所需的物件。因此我們可以知道,此模式的重點在於 client 的程式碼可以在不知道特定類別為何的情形下可以生成新的物件。
接下來來看簡單的範例程式碼吧。在 Java 中,每個類別都繼承了 Object 這個類別,表示每個類別都含有 clone() 這個方法。但是要讓 clone() 能動,類別還必須實作 java.lang.Cloneable 這個標籤介面(Tag Interface,Marker Interface)。除了這點之外,還要注意你的 clone() 是想要淺層複製 (shallow copy) 還是深層複製 (deep copy)。
// 在 Java, 要實作 Cloneable // 才能 override Object 的 clone() 方法 public class SomeObj implements Cloneable { // 某個 primitive type 成員, // shallow copy 可以複製值 private int mNum; // 某個類別物件, // shallow copy 只會複製 reference, private Obj mObj; @Override public SomeObj clone() { SomeObj obj = null; try { // 先做原物件的複製 obj = (SomeObj)super.clone(); // 再做物件成員的複製, // 假設 Obj 類別也有做好 clone() obj.setObj(mObj.clone()); } catch(CloneNotSupportedException e) { e.printStackTrace(); } } public void setObj(Obj obj) { mObj = obj; } }有人可能會有疑問,原型模式跟抽象工廠模式都是生成物件,這兩個有什麼差別呢?其實很多時候生成物件的設計模式沒有很大的區別,就 client 的角度都是透過某個方法就能取得物件,但對於物件類別的架構而言,使用原型模式的話,子類別不用繼承父類別來達到其他功能 (Subclassing),但需要有初始化的行為 (總要先產生一個物件,之後才能用 clone 的);而抽象工廠模式通常是利用工廠方法來取得物件,而工廠方法需要 subclassing。
參考資料:
深入淺出設計模式
Explanation of Deep and Shallow Copying
留言
張貼留言