設計模式系列 原型模式 Prototype

2022-02-18 14:23:50 字數 3046 閱讀 8605

意圖

用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。

場景

遊戲場景中的有很多相似的敵人,它們的技能都一樣,但是隨著敵人出現的位置不同,這些人的能力不太一樣。假設,我們現在需要把三個步兵組成一隊,其中還有乙個精英步兵,能力特別高。那麼,你或許可以建立乙個敵人抽象類,然後對於不同能力的步兵建立不同的子類。然後,使用工廠方法等設計模式讓呼叫方依賴敵人抽象類。

問題來了,如果有無數種能力不同步兵,難道需要建立無數子類嗎?還有,步兵模型的初始化工作是非常耗時的,建立這麼多步兵物件可能還會浪費很多時間。我們是不是可以通過只建立乙個步兵原型,然後複製出多個一摸一樣的步兵呢?複製後,只需要調整一下這些物件在地圖上出現的位置,或者調整一下它們的能力即可。原型模式就是用來解決這個問題的。

示例**

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.原型模式可以簡單理解為拷貝原型物件得到新的物件。想象乙個配鑰匙的小店,給店主乙個原有...

設計模式 原型模式

魔術師手拿一張百元大鈔,瞬間又變出兩張。也像配鑰匙一樣,拿一把鑰匙,老師傅就能做出另乙個一模一樣的。像這種複製我們並不陌生,類似於我們設計中的原型模式 本文將從以下幾點 原型模式 概述 結構圖 淺複製深複製 總結 用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。允許乙個物件再建立另外...