外國人把那京戲叫做“Beijing Opera ” 沒見過那五色的油彩楞往臉上畫,四擊頭一亮相,(哇……)美極了妙極了,簡直“ok”頂呱呱 ,藍臉的多爾敦盜御馬,紅臉的關公戰長沙 ,黃臉的典韋白臉的曹操 ,黑臉的張飛叫喳喳…… ,細心的小朋友,仔細區分就會發現,雖然每個京劇演員都不同,但基本上只具有幾種臉型,長方形,圓形,細長,然后配上不同的妝容,胡子,眉毛,頭飾,服裝,有的再加點兒裝飾物,就成了我們所看到的不同的演員角色,國粹和我們的編程有著什么樣的聯系呢?用面向對象的方法來說就是,我們先建立一個原型,然后通過對原型進行復制和修飾的方法,就可以產生一個和原型相似的新對象,用GOF的話來說就是,用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。
在大話設計模式,簡歷復印-原型模式這一節中,當我們創建一個類的實例的過程很復雜,并且我們需要創建多個這樣類的實例時,如果我們用new操作符去創建這樣的類實例,這未免會增加創建類的復雜度和耗費更多的內存空間,因為這樣在內存中分配了多個一樣的類實例對象,然后如果采用工廠模式來創建這樣的系統的話,隨著產品類的不斷增加,導致子類的數量不斷增多,反而增加了系統復雜程度,所以在這里使用工廠模式來封裝類創建過程并不合適,然而原型模式可以很好地解決這個問題,因為每個類實例都是相同的,當我們需要多個相同的類實例時,沒必要每次都使用new運算符去創建相同的類實例對象,此時我們一般思路就是想——只創建一個類實例對象,如果后面需要更多這樣的實例,可以通過對原來對象拷貝一份來完成創建,這樣在內存中不需要創建多個相同的類實例,從而減少內存的消耗和達到類實例的復用。 然而這個思路正是原型模式的實現方式。下面我們來看看原型模式的結構圖:
? ? ? ??
前天,晚上放學回宿舍,一個不小心把鑰匙弄丟了,結果進不了宿舍門,要是兩個不小心還得了,嗚嗚,謝謝穎杰幫我開門,沒辦法啊,總要人家開門多不好,還是自己配一把吧,宿舍鑰匙和車鑰匙在一個鑰匙圈上,幸好車鑰匙還有一把備份,找個時間去配一把宿舍鑰匙和車鑰匙,次日中午我拿著穎杰的鑰匙,來到中門,配鑰匙的師傅的手藝可真是熟練啊,只見我把鑰匙給了他,他直接找一個合適的鑰匙胚子,把我的鑰匙夾在配鑰匙機的一端,胚子夾在另一端,一開電源,一把標尺比著我的鑰匙齒型走一遍,砂輪就在胚子上復制出一把鑰匙來!一分鐘不到,兩把新鑰匙就搞定了!這里的舊鑰匙是一個原型。配鑰匙的過程就是根據我提供的原型,再復制一份出來,就有了一個新的鑰匙。兩個鑰匙完全一樣。我可以給新配的鑰匙加上一個標簽,以表明是我的,不能和穎杰的弄混了,再來看看我們的代碼是如何實現的呢:
~~~
namespace?Prototype??
{??
????//抽象鑰匙原型??
????public?abstract?class?Key??
????{??
????????private?string?name;??
???
????????public?string?Name??
????????{??
????????????get?{?return?name;?}??
????????????set?{?name?=?value;?}??
????????}??
????????private?string?owner;??
???
????????public?string?Owner??
????????{??
????????????get?{?return?owner;?}??
????????????set?{?owner?=?value;?}??
????????}??
????????public?Key(string?name,?string?owner)??
????????{??
????????????this.name?=?name;??
????????????this.owner?=?owner;??
????????}??
????????//鑰匙復制自身的抽象定義??
????????public?abstract?Key?Clone();??
????????public?override?String?ToString()??
????????{??
????????????return?this.Name?+?",?belongs?to?"?+?this.Owner;??
????????}??
????}??
????//宿舍鑰匙??
????public?class?DormitoryKey?:?Key??
????{??
????????public??DormitoryKey(string?owner)?:?base("?Dormitory?Key",?owner)?{?}??
???
????????public?override?Key?Clone()??
????????{??
????????????return?new??DormitoryKey(this.Owner);??
????????}??
????}??
????//自行車鑰匙??
????public?class?BicycleKey?:?Key??
????{??
????????public?BicycletKey(string?owner)?:?base("Bicycle?Key",?owner)?{?}??
???
????????public?override?Key?Clone()??
????????{??
????????????return?new?BicycleKey(this.Owner);??
????????}??
????}??
????//客戶端調用方法??
????public?class?Client??
????{??
????????public?static?void?Main(string[]?args)??
????????{??
????????????Key?oldDormitoryKey,?newDormitoryKey,?oldBicycleKey,?newBicycleKey;??
????????????oldDormitoryKey?=?new?DormitoryKey("yingjie");??
????????????newDormitoryKey?=?oldDormitoryKey.Clone();??
????????????newDormitoryKey.Owner?=?"Me";??
????????????oldBicycleKey?=?new?BicycleKey("Me");??
????????????newBicycleKey?=?oldBicycleKey.Clone();??
????????????newBicycleKey.Owner?=?"yingjie";??
???
????????????Console.WriteLine(oldDormitoryKey);??
????????????Console.WriteLine(newDormitoryKey);??
????????????Console.WriteLine(oldBicycleKey);??
????????????Console.WriteLine(newBicycleKey);??
????????}??
????}??
}??
~~~
原型模式在生成復雜對象比較苦難的環境中比較適用,通過克隆已有對象來實現創建新的對象,節省了時間和空間,原型模式應用于希望系統獨立于產品的創建、表示和構成時,這和工廠模式很類似。事實上,和工廠模式相同的是,原型模式同樣對客戶隱藏了對象的創建工作,但是,與工廠模式通過對一個類進行實例化來構造新對象不同的是,原型模式是通過拷貝一個現有對象生成新對象的。工廠模式適用于產品種類有限的情況下,當產品數量巨大或需要提供動態產品增刪等性能時,使用原型模式具有更強的適應性。設計之旅,未完待續......