1. 程式人生 > >Head First設計模式之訪問者模式

Head First設計模式之訪問者模式

back visitor 這樣的 耦合 擴展性 表示 accept struct system

一、定義

定義:表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素類的前提下定義作用於這些元素的新操作。

訪問者模式適用於數據結構相對穩定的系統, 它把數據結構和作用於數據結構之上的操作之間的耦合度降低,使得操作集合可以相對自由地改變。

數據結構的每一個節點都可以接受一個訪問者的調用,此節點向訪問者對象傳入節點對象,而訪問者對象則反過來執行節點對象的操作。這樣的過程叫做“雙重分派”。節點調用訪問者,將它自己傳入,訪問者則將某算法針對此節點執行。

二、結構圖

技術分享

  這裏需要明確一點:訪問者模式中具體訪問者的數目和具體節點的數目沒有任何關系。從訪問者的結構圖可以看出,訪問者模式涉及以下幾類角色。

  • 抽象訪問者角色(Vistor):聲明一個活多個訪問操作,使得所有具體訪問者必須實現的接口。
  • 具體訪問者角色(ConcreteVistor):實現抽象訪問者角色中所有聲明的接口。
  • 抽象節點角色(Element):聲明一個接受操作,接受一個訪問者對象作為參數。
  • 具體節點角色(ConcreteElement):實現抽象元素所規定的接受操作。
  • 結構對象角色(ObjectStructure):節點的容器,可以包含多個不同類或接口的容器。

三、適用場景

1、對象結構中對象對應的類很少改變,但經常需要在此對象結構上定義新的操作。

2、需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而需要避免讓這些操作"汙染"這些對象的類,也不希望在增加新操作時修改這些類。

四、優缺點

優點: 1、符合單一職責原則。 2、優秀的擴展性。 3、靈活性。

缺點: 1、具體元素對訪問者公布細節,違反了迪米特原則。 2、具體元素變更比較困難。 3、違反了依賴倒置原則,依賴了具體類,沒有依賴抽象。

五、實現

思路:商家定義了一個套餐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.cnblogs.com/zhili/p/VistorPattern.html

http://www.cnblogs.com/JsonShare/p/7380772.html

歡迎閱讀本系列文章:Head First設計模式之目錄

Head First設計模式之訪問者模式