意圖
用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。
場景
遊戲場景中的有很多相似的敵人,它們的技能都一樣,但是隨著敵人出現的位置不同,這些人的能力不太一樣。假設,我們現在需要把三個步兵組成一隊,其中還有乙個精英步兵,能力特別高。那麼,你或許可以建立乙個敵人抽象類,然後對於不同能力的步兵建立不同的子類。然後,使用工廠方法等設計模式讓呼叫方依賴敵人抽象類。
問題來了,如果有無數種能力不同步兵,難道需要建立無數子類嗎?還有,步兵模型的初始化工作是非常耗時的,建立這麼多步兵物件可能還會浪費很多時間。我們是不是可以通過只建立乙個步兵原型,然後複製出多個一摸一樣的步兵呢?複製後,只需要調整一下這些物件在地圖上出現的位置,或者調整一下它們的能力即可。原型模式就是用來解決這個問題的。
示例**
using system; using system.collections.generic; using system.linq; using system.text;
//引用命名空間 using system.threading; using system.runtime.serialization.formatters.binary; using system.io;
namespace prototype_moshi } [serializable] class loaction } [serializable] abstract class enemy set } private int power; public int power set } private int speed;
public int speed set
} public abstract enemy clone(bool is_deep_copy);//此抽象方法實現的就是實現本身類的複製、經典之處 public abstract void show_info(); public enemy(int power, int speed, loaction location)
} [serializable] class foot_man : enemy public override void show_info() power: location:, ", model, power, speed, location._x, location._y); } public override enemy clone(bool is_deep_copy) else foot_man = (foot_man)this.memberwiseclone(); return foot_man;
}
public void foot_man_attack() } }
**說明
l enemy類是抽象原型,它有兩個用途,一是定義了原型的一些抽象內容,二是定義了原型模式必須的拷貝方法。在這裡,我們看到,每個敵人的屬性有位置、攻擊力、速度等,並且能通過showinfo()方法來獲取這個人的資訊。
l footman類就是具體原型了,它顯示了敵人的具體引數以及實現了轉殖自身。
l gamescene類就是呼叫方,在這裡我們並沒有看到有和具體原因進行依賴,通過複製傳入的轉殖原型,得到一些新的敵人,在原型的基礎上稍微調整一下就變成了一支敵人部隊。
l 原型模式通過對原型進行轉殖來替代無數子類,因此也就減少了呼叫方和具體型別產生依賴的程式。
l clone()方法接受乙個引數,表示是否是深拷貝。在這裡,我們通過序列化反序列化實現深拷貝,深拷貝實現物件的完整複製,包括物件內部的引用型別都會複製乙份全新的。在這裡,如果3個敵人物件的location都指向記憶體同乙個位址的話,那麼它們就分不開了,因此,在複製的時候需要進行深拷貝,使得它們的location是獨立的。
l 在初始化enemy的時候,我們sleep()了一下,目的是模擬物件的建立是乙個非常耗時的工作,這也體現了原型模式的另乙個優勢,在生成敵人的時候,我們其實無需再做這些工作了,我們只需要得到它的完整資料,並且進行一些修改就是乙個新的敵人。
l 執行程式後可以看到,雖然建立了三個敵人,但是只耗費了乙個敵人的建立時間,三個敵人都是從原型轉殖出來的。由於進行了深拷貝,修改了乙個敵人的位置並不會影響其它敵人。
何時採用
l 從**角度來說, 如果你希望執行時指定具體類(比如是使用footman作為敵人還是使用其它),或者你希望避免建立物件時的初始化過程(如果這個過程占用的時間和資源都非常多),或者是希望避免使用工廠方法來實現多型的時候,可以考慮原型模式。
實現要點
l .net中使用object的memberwiseclone()方法來實現淺拷貝,通過序列化和反序列化實現深拷貝,後者代價比較大,選擇何時的拷貝方式。
l 原型模式同樣需要抽象型別和具體型別,通過相對穩定的抽象型別來減少或避免客戶端的修改可能性。
l 在**中,我們把敵人作為了抽象型別,抽象層次很高。完全可以把步兵作為抽象型別,下面有普通步兵,手榴彈步兵等等,再有乙個坦克作為抽象型別,下面還有普通坦克和防飛彈坦克。這樣gamescene可能就需要從兩種抽象型別轉殖出許多步兵和坦克。不管怎麼樣抽象,只要是物件型別由原型例項所指定,新物件通過原型例項做拷貝,那麼這就是原型模式。
注意事項
l 注意選擇深拷貝和淺拷貝。
l 拷貝原型並進行修改意味著原型需要公開更多的資料,對已有系統實現原型模式可能修改的代價比較大。
iOS 21種設計模式之原型模式Prototype
我的stackoverflow 感謝 pro objective c design pattern for ios 一書,這個部落格系列由很多靈感源自次書。同時,也感謝wiki以及一些部落格博主。每篇文章最後,都會列出參考鏈結。物件建立模式 設計模式是為了解決一類問題而出現的,要深刻理解某個模式的應...
設計模式 原型模式
1.首先分析原型模式的由來 一般來說,建立乙個物件可以由以下方法 知道物件的具體型別,直接用new生成。不知道型號,知道相應的需求,可以使用工廠方法模式。根據乙個已有的物件來複製為乙個新的物件,可以使用原型模式。2.原型模式可以簡單理解為拷貝原型物件得到新的物件。想象乙個配鑰匙的小店,給店主乙個原有...
設計模式 原型模式
魔術師手拿一張百元大鈔,瞬間又變出兩張。也像配鑰匙一樣,拿一把鑰匙,老師傅就能做出另乙個一模一樣的。像這種複製我們並不陌生,類似於我們設計中的原型模式 本文將從以下幾點 原型模式 概述 結構圖 淺複製深複製 總結 用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。允許乙個物件再建立另外...