Head First設計模式之訪問者模式
一、定義
定義:表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素類的前提下定義作用于這些元素的新操作。
訪問者模式適用于數(shù)據(jù)結構相對穩(wěn)定的系統(tǒng), 它把數(shù)據(jù)結構和作用于數(shù)據(jù)結構之上的操作之間的耦合度降低,使得操作集合可以相對自由地改變。
數(shù)據(jù)結構的每一個節(jié)點都可以接受一個訪問者的調用,此節(jié)點向訪問者對象傳入節(jié)點對象,而訪問者對象則反過來執(zhí)行節(jié)點對象的操作。這樣的過程叫做“雙重分派”。節(jié)點調用訪問者,將它自己傳入,訪問者則將某算法針對此節(jié)點執(zhí)行。
二、結構圖

這里需要明確一點:訪問者模式中具體訪問者的數(shù)目和具體節(jié)點的數(shù)目沒有任何關系。從訪問者的結構圖可以看出,訪問者模式涉及以下幾類角色。
- 抽象訪問者角色(Vistor):聲明一個活多個訪問操作,使得所有具體訪問者必須實現(xiàn)的接口。
- 具體訪問者角色(ConcreteVistor):實現(xiàn)抽象訪問者角色中所有聲明的接口。
- 抽象節(jié)點角色(Element):聲明一個接受操作,接受一個訪問者對象作為參數(shù)。
- 具體節(jié)點角色(ConcreteElement):實現(xiàn)抽象元素所規(guī)定的接受操作。
- 結構對象角色(ObjectStructure):節(jié)點的容器,可以包含多個不同類或接口的容器。
三、適用場景
1、對象結構中對象對應的類很少改變,但經常需要在此對象結構上定義新的操作。
2、需要對一個對象結構中的對象進行很多不同的并且不相關的操作,而需要避免讓這些操作"污染"這些對象的類,也不希望在增加新操作時修改這些類。
四、優(yōu)缺點
優(yōu)點: 1、符合單一職責原則。 2、優(yōu)秀的擴展性。 3、靈活性。
缺點: 1、具體元素對訪問者公布細節(jié),違反了迪米特原則。 2、具體元素變更比較困難。 3、違反了依賴倒置原則,依賴了具體類,沒有依賴抽象。
五、實現(xiàn)
思路:商家定義了一個套餐A,為套餐A添加了土豆和花生,然后張三、李四才點了套餐A。
好處:不管多少人來,都是給他們的菜都是一樣的
壞處:如果套餐A 突然加了一個菜 海帶, 導致所有人都要來拿海帶,所以變化是非常困難的。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DesignPatterns.Visitor { class Program { static void Main(string[] args) { Food a = new Potato(); Food b = new Peanut(); var combo = new Combo(); combo.Add(a); combo.Add(b); Visitor charger = new Charger("張三"); Visitor workerOfPharmacy = new WorkerOfPharmacy("李四"); combo.Accpet(charger); Console.WriteLine(); combo.Accpet(workerOfPharmacy); } } /// <summary> /// 抽象訪問者 /// </summary> public abstract class Visitor { protected string name { get; set; } public Visitor(string name) { this.name = name; } public abstract void visitor(Potato a); public abstract void visitor(Peanut b); } /// <summary> /// 具體訪問者:張三 /// </summary> public class Charger : Visitor { public Charger(string name) : base(name) { } public override void visitor(Potato a) { Console.WriteLine("張三:" + this.name + " 取菜 " + a.GetName()); } public override void visitor(Peanut b) { Console.WriteLine("張三:" + this.name + " 取菜 " + b.GetName()); } } /// <summary> /// 具體訪問者:李四 /// </summary> public class WorkerOfPharmacy : Visitor { public WorkerOfPharmacy(string name) : base(name) { } public override void visitor(Potato a) { Console.WriteLine("李四:" + this.name + " 取菜 " + a.GetName() ); } public override void visitor(Peanut b) { Console.WriteLine("李四:" + this.name + " 取菜 " + b.GetName()); } } /// <summary> /// 抽象元素:食物 /// </summary> public abstract class Food { protected string name { get; set; } public Food() { name = "我是食物"; } public string GetName() { return name; } public abstract void Accept(Visitor visitor); } /// <summary> /// 具體元素:土豆 /// </summary> public class Potato : Food { public Potato() { this.name = "土豆"; } public override void Accept(Visitor visitor) { visitor.visitor(this); } } /// <summary> /// 具體元素:花生 /// </summary> public class Peanut : Food { public Peanut() { this.name = "花生"; } public override void Accept(Visitor visitor) { visitor.visitor(this); } } /// <summary> /// 具體元素:套餐 /// </summary> public class Combo { private List<Food> list = new List<Food>(); public void Accpet(Visitor visitor) { foreach (var item in list) { item.Accept(visitor); } } public void Add(Food med) { list.Add(med); } public void Remove(Food med) { list.Remove(med); } } }
參考
http://blog.csdn.net/heyangyi_19940703/article/details/51374416
http://www.rzrgm.cn/zhili/p/VistorPattern.html
http://www.rzrgm.cn/JsonShare/p/7380772.html
歡迎閱讀本系列文章:Head First設計模式之目錄

浙公網(wǎng)安備 33010602011771號