原型
原型模式:當(dāng)創(chuàng)建給定類的過程很昂貴或很復(fù)雜時,就使用原型模式。
我們在進(jìn)行游戲的時候游戲會動態(tài)創(chuàng)建怪,而怪時根據(jù)場景的不同而變化創(chuàng)建的,英雄自己也會創(chuàng)建一些隨從。創(chuàng)建各式各樣的怪獸實例,已經(jīng)越來越麻煩,將各種狀態(tài)細(xì)節(jié)放再構(gòu)造器中,看起來一點都不內(nèi)聚。如果能夠在單一區(qū)域內(nèi)封裝所有的實例化細(xì)節(jié),能夠?qū)⒇?fù)責(zé)處理創(chuàng)建怪獸的細(xì)節(jié)代碼,從實際需要動態(tài)創(chuàng)建實例的代碼中解耦,那么程序?qū)⒆兊孟喈?dāng)干凈。
原型模式通過復(fù)制現(xiàn)有的實例來創(chuàng)建新的實例,通常使用clone方法,或者反序列化。
設(shè)計類圖:
原型模式中有三個角色:
原型角色:定義用于復(fù)制現(xiàn)有實例來生成新實例的方法(Monster)。
具體原型角色:實現(xiàn)用于復(fù)制現(xiàn)有實例來生成新實例的方法(WellKnowMonster,DynamicGeneratedMonster)。
使用者角色:維護(hù)一個注冊表,并提供一個找出正確實例原型的方法。最后,提供一個獲取新實例的方法,用來委托復(fù)制實例的方法生成新實例。
實現(xiàn)代碼:
①原型角色
1 public interface Monster 2 { 3 public Monster Clone(); 4 }
②具體原型角色
1 public class WellKnowMonster : Monster 2 { 3 public Monster Clone() 4 {
5 Monster clone =
JsonConvert.DeserializeObject<WellKnowMonster>(JsonConvert.SerializeObject(this
)); 6 return clone; 7 } 8 } 9 10 11 public class DynamicGeneratedMonster :
Monster12 { 13 public Monster Clone() 14 { 15 Monster clone =
JsonConvert.DeserializeObject<DynamicGeneratedMonster>(JsonConvert.SerializeObject(
this)); 16 return clone; 17 } 18 }
③使用者角色
1 public class MonsterRegistry 2 { 3 Dictionary<string, Monster>
monsterDic =new Dictionary<string, Monster>(); 4 public void RegisterMonster(
string key,Monster monster) { 5 monsterDic.Add(key, monster); 6 } 7 public
Monster GetMonster(string key) { 8 Monster monster = monsterDic[key]; 9 return
monster.Clone();10 } 11 }
④測試
?優(yōu)點:
1、向客戶隱藏制造新實例的復(fù)雜性。
2、提供讓客戶能夠產(chǎn)生未知類型對象的選項。
3、在某些環(huán)境下,復(fù)制對象比創(chuàng)建新對象更有效。
用途和缺點:
1、在一個復(fù)雜的類層次中,當(dāng)系統(tǒng)必須從許多類型創(chuàng)建新對象時,可以考慮原型。
2、使用原型模式的缺點,對象的復(fù)制有時候相當(dāng)復(fù)雜。
訪問者
訪問者模式:當(dāng)你想要為一個對象的組合增加新的能力,且封裝并不重要時,就使用訪問者模式。
當(dāng)餐廳里面來了顧客,可能顧客會詢問菜單的信息(比如這個辣不辣,這個味道重不重之類的),甚至有些會詢問原材料的成分。
我們像這樣設(shè)計在每個地方加入新方法,如果增加了新方法我們就必須在兩個地方加入新方法,萬一多了新的菜單我們就必須修改三個地方。這種情況我們就可以使用訪問者模式。通過訪問者訪問組合內(nèi)的每個元素,收集組合中所有對象的狀態(tài)。一旦狀態(tài)被收集了,客戶就可以讓訪問者對狀態(tài)進(jìn)行各種操作。當(dāng)需要新的功能時,只要加強(qiáng)訪問者即可。
?實現(xiàn)代碼:
①實現(xiàn)菜單,菜單項接口定義GetState方法
1 public interface MenuComponent 2 { 3 public void GetState(Visitor
visitor); 4 } 5 6 7 //菜單 8 public class Menu : MenuComponent 9 { 10
public string displayInfo = "不辣,口味適中"; 11 public void GetState(Visitor visitor)
12 { 13 visitor.Visit(this); 14 } 15 } 16 17 //原料 18 public class
Ingredients : MenuComponent19 { 20 public string displayInfo = "不辣,偏咸"; 21
public void GetState(Visitor visitor) 22 { 23 visitor.Visit(this); 24 } 25 }
②訪問者,訪問者定義接口以便菜單項使用接口類型
public interface Visitor { public void Visit(Menu menu); public void
Visit(Ingredients ingredients); }class MenuVisitor : Visitor { public void
Visit(Menu menu) { Console.WriteLine(menu.displayInfo); }public void
Visit(Ingredients ingredients) { Console.WriteLine(ingredients.displayInfo); } }
③測試
優(yōu)點:
1、允許你對組合結(jié)構(gòu)加入新的操作,而無需改變結(jié)構(gòu)本身。
2、想加入新操作相對容易。
3、訪問者所進(jìn)行的操作,其代碼是集中在一起的。
用途和缺點:
1、當(dāng)采用訪問者模式的時候,就會打破組合類的封裝。
2、因為訪問模式的加入需要對每個像進(jìn)行訪問,所以對組合結(jié)構(gòu)的改變更加困難。
熱門工具 換一換