前言
在軟件系統(tǒng)中,當(dāng)創(chuàng)建一個(gè)類的實(shí)例的過(guò)程很昂貴或很復(fù)雜,并且我們需要?jiǎng)?chuàng)建多個(gè)這樣類的實(shí)例時(shí),如果我們用new操作符去創(chuàng)建這樣的類實(shí)例,這就會(huì)增加創(chuàng)建類的復(fù)雜度和創(chuàng)建過(guò)程與客戶代碼復(fù)雜的耦合度。如果采用工廠模式來(lái)創(chuàng)建這樣的實(shí)例對(duì)象的話,隨著產(chǎn)品類的不斷增加,導(dǎo)致子類的數(shù)量不斷增多,也導(dǎo)致了相應(yīng)工廠類的增加,維護(hù)的代碼維度增加了,因?yàn)橛挟a(chǎn)品和工廠兩個(gè)維度了,反而增加了系統(tǒng)復(fù)雜程度,所以在這里使用工廠模式來(lái)封裝類創(chuàng)建過(guò)程并不合適。由于每個(gè)類實(shí)例都是相同的,這個(gè)相同指的是類型相同,但是每個(gè)實(shí)例的狀態(tài)參數(shù)會(huì)有不同,如果狀態(tài)數(shù)值也相同就沒(méi)意義了,有一個(gè)這樣的對(duì)象就可以了。當(dāng)我們需要多個(gè)相同的類實(shí)例時(shí),可以通過(guò)對(duì)原來(lái)對(duì)象拷貝一份來(lái)完成創(chuàng)建,這個(gè)思路正是原型模式的實(shí)現(xiàn)方式。
原型模式的定義
在軟件系統(tǒng)中,經(jīng)常面臨著“某些結(jié)構(gòu)復(fù)雜的對(duì)象”的創(chuàng)建工作;由于需求的變化,這些對(duì)象經(jīng)常面臨著劇烈的變化,但是它們卻擁有比較穩(wěn)定一致的接口。如何應(yīng)對(duì)這種變化?如何向“客戶程序”隔離出“這些易變對(duì)象”,從而使得“依賴這些易變對(duì)象的客戶程序”不隨著需求改變而改變?那就是原型模式,使用原型實(shí)例指定創(chuàng)建對(duì)象的種類,然后通過(guò)拷貝這些原型來(lái)創(chuàng)建新的對(duì)象。
原型模式的組成
原型類(Prototype):原型類,聲明一個(gè)Clone自身的接口;
(資料圖)
具體原型類(ConcretePrototype):實(shí)現(xiàn)一個(gè)Clone自身的操作。
在原型模式中,Prototype通常提供一個(gè)包含Clone方法的接口,具體的原型ConcretePrototype使用Clone方法完成對(duì)象的創(chuàng)建。
原型模式的實(shí)現(xiàn)
《大話西游之大圣娶親》這部電影,沒(méi)看過(guò)的人不多吧,里面有這樣一個(gè)場(chǎng)景。牛魔王使用無(wú)敵牛虱大戰(zhàn)至尊寶,至尊寶的應(yīng)對(duì)之策就是,從腦后把下一撮猴毛,吹了口仙氣,無(wú)數(shù)猴子猴孫現(xiàn)身,來(lái)大戰(zhàn)牛魔王的無(wú)敵牛虱。至尊寶的猴子猴孫就是該原型模式的最好體現(xiàn)。至尊寶創(chuàng)建自己的一個(gè)副本,不用還要重新孕育五百年,然后出世,再學(xué)藝,最后來(lái)和老牛大戰(zhàn),估計(jì)黃花菜都涼了。他有3根救命猴毛,輕輕一吹,想要多少個(gè)自己就有多少個(gè),方便,快捷。
抽象原型
/// /// 抽象原型,定義了原型本身所具有特征和動(dòng)作,該類型就是至尊寶 /// public abstract class Prototype { /// /// 戰(zhàn)斗--保護(hù)師傅 /// public abstract void Fight(); /// /// 化緣--不要餓著師傅 /// public abstract void BegAlms(); /// /// 吹口仙氣--變化一個(gè)自己出來(lái) /// /// public abstract Prototype Clone(); }
具體原型
創(chuàng)建兩個(gè)具體原型:行者孫和孫行者
行者孫:
/// /// 具體原型,例如:行者孫,他只負(fù)責(zé)化齋飯食和與天界寵物下界的妖怪的戰(zhàn)斗 /// public sealed class XingZheSunPrototype : Prototype { /// /// 戰(zhàn)斗--保護(hù)師傅--與自然修煉成妖的戰(zhàn)斗 /// public override void Fight() { Console.WriteLine("行者孫:騰云駕霧,與天界寵物下界的妖怪的戰(zhàn)斗...."); } /// /// 化緣--不要餓著師傅--飯食類 /// public override void BegAlms() { Console.WriteLine("行者孫:化緣雞魚肉蛋...."); } /// /// 吹口仙氣--變化一個(gè)自己出來(lái) /// /// public override Prototype Clone() { return (XingZheSunPrototype)this.MemberwiseClone(); } }
孫行者:
/// /// 具體原型,例如:孫行者,他只負(fù)責(zé)與自然界修煉成妖的戰(zhàn)斗和化齋水果 /// public sealed class SunXingZhePrototype : Prototype { /// /// 戰(zhàn)斗--保護(hù)師傅-與天界寵物戰(zhàn)斗 /// public override void Fight() { Console.WriteLine("孫行者:騰云駕霧,與自然界修煉成妖的戰(zhàn)斗...."); } /// /// 化緣--不要餓著師傅---水果類 /// public override void BegAlms() { Console.WriteLine("孫行者:化緣水果...."); } /// /// 吹口仙氣--變化一個(gè)自己出來(lái) /// /// public override Prototype Clone() { return (SunXingZhePrototype)this.MemberwiseClone(); } }
調(diào)用
public void RunTest() { //原型行者孫 Prototype xingZheSun = new XingZheSunPrototype(); Prototype xingZheSun2 = xingZheSun.Clone(); Prototype xingZheSun3 = xingZheSun.Clone(); //1號(hào)行者孫打妖怪 xingZheSun.Fight(); //2號(hào)行者孫去化緣 xingZheSun3.BegAlms(); Console.WriteLine("\r\n*****************************\r\n"); //原型孫行者 Prototype sunXingZhe = new SunXingZhePrototype(); Prototype sunXingZhe2 = sunXingZhe.Clone(); Prototype sunXingZhe3 = sunXingZhe.Clone(); Prototype sunXingZhe4 = sunXingZhe.Clone(); Prototype sunXingZhe5 = sunXingZhe.Clone(); //1號(hào)孫行者打妖怪 sunXingZhe.Fight(); //2號(hào)孫行者去化緣 sunXingZhe2.BegAlms(); //戰(zhàn)斗和化緣也可以分類,比如化緣,可以分:水果類化緣,飯食類化緣;戰(zhàn)斗可以分為:天界寵物下界成妖的戰(zhàn)斗,自然修煉成妖的戰(zhàn)斗,大家可以自己去想吧,原型模式還是很有用的 }
原型模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
原型模式向客戶隱藏了創(chuàng)建新實(shí)例的復(fù)雜性。
原型模式允許動(dòng)態(tài)增加或較少產(chǎn)品類。
原型模式簡(jiǎn)化了實(shí)例的創(chuàng)建結(jié)構(gòu),工廠方法模式需要有一個(gè)與產(chǎn)品類等級(jí)結(jié)構(gòu)相同的等級(jí)結(jié)構(gòu),而原型模式不需要這樣。
產(chǎn)品類不需要事先確定產(chǎn)品的等級(jí)結(jié)構(gòu),因?yàn)樵湍J竭m用于任何的等級(jí)結(jié)構(gòu)。
缺點(diǎn)
每個(gè)類必須配備一個(gè)克隆方法。
配備克隆方法需要對(duì)類的功能進(jìn)行通盤考慮,這對(duì)于全新的類不是很難,但對(duì)于已有的類不一定很容易,特別當(dāng)一個(gè)類引用不支持串行化的間接對(duì)象,或者引用含有循環(huán)結(jié)構(gòu)的時(shí)候。
關(guān)鍵詞: