說明:
當一個「物件結構」中的「元素」幾乎不會異動,但這些「元素的行為」常會增減,則適合用訪問者模式。
訪問者模式是將「元素的行為」,提取出來,每一種行為做成一個 「Visitor(訪問者) 物件」,
每一個 「Visitor(訪問者) 物件」,都能依據不同的「元素」,對應到不同的行為結果。
範例:
在一個遊戲結構中,有兩種人,誠實人、說謊人。
誠實人都說真話,說謊人都說假話。
誠實人、說謊人即是不會異動的元素,
但對誠實人、說謊人「提出的問題」,是可能會改變的,
所以「提出的問題」即可當作「Visitor(訪問者) 物件」,用訪問者模式 (Visitor Pattern),對以後要增減「提出的問題」是較方便的。
(但若要新增第三種人則較麻煩)
希望達成如下的效果
static void Main(string[] args) { // 物件結構 ObjectStructure o = new ObjectStructure(); // 誠實人元素物件 HonestManElement honestMan = new HonestManElement(); // 說謊人元素物件 LieManElement lieMan = new LieManElement(); // 將誠實人、說謊人元素物件放進物件結構 o.Attach(honestMan); o.Attach(lieMan); // 數學問題訪問者 MathVisitor mathVisitor = new MathVisitor(); Console.WriteLine("[數學問題]"); o.Display(mathVisitor); // 輸出結果 // 物理問題訪問者 PhysicsVisitor physicsVisitor = new PhysicsVisitor(); Console.WriteLine("[物理問題]"); o.Display(physicsVisitor); // 輸出結果 Console.Read(); }執行結果:
[數學問題] 誠實人 說: 1+1=2 說謊人 說: 1+1=3 [物理問題] 誠實人 說: 鐵球在水中會沉下去 說謊人 說: 鐵球在水中會浮起來
實現的重點在於,物件往返傳了兩次,
第一次是「Visitor物件」經由「結構物件」傳給「元素物件」
第二次是「元素物件」將自己傳給「Visitor物件」,以便「Visitor物件」依不同的「元素物件」執行不同的方法。
其餘程式碼
// 物件結構 class ObjectStructure { private List<Element> elements = new List<Element>(); //增加元素物件 public void Attach(Element element) { elements.Add(element); } //移除元素物件 public void Detach(Element element) { elements.Remove(element); } //顯示 public void Display(Visitor visitor) { foreach (Element e in elements) { e.Accept(visitor); } } } // 元素抽像類別 (要放入物件結構中) abstract class Element { // 每個元素要能接收訪問者物件,以便再將自己傳給訪問者 public abstract void Accept(Visitor visitor); } // 誠實人元素物件 class HonestManElement : Element { public string name = "誠實人"; public override void Accept(Visitor visitor) { // 將自己傳給訪問者,以便訪問者分辨、執行適合自己的行為 visitor.visit(this); } } // 說謊人元素物件 class LieManElement : Element { public string name = "說謊人"; public override void Accept(Visitor visitor) { // 將自己傳給訪問者,以便訪問者分辨、執行適合自己的行為 visitor.visit(this); } } // 訪問者 (能根據不同元素,產生不同結果) abstract class Visitor { // 訪問誠實人的多載方法 public abstract void visit(HonestManElement honestElement); // 訪問說謊人的多載方法 public abstract void visit(LieManElement lieElement); } // 數學問題訪問者 class MathVisitor : Visitor { // 訪問誠實人的多載方法 public override void visit(HonestManElement honestElement) { Console.WriteLine("{0} 說: 1+1=2", honestElement.name); } // 訪問說謊人的多載方法 public override void visit(LieManElement lieElement) { Console.WriteLine("{0} 說: 1+1=3", lieElement.name); } } // 物理問題訪問者 class PhysicsVisitor : Visitor { // 訪問誠實人的多載方法 public override void visit(HonestManElement honestElement) { Console.WriteLine("{0} 說: 鐵球在水中會沉下去", honestElement.name); } // 訪問說謊人的多載方法 public override void visit(LieManElement lieElement) { Console.WriteLine("{0} 說: 鐵球在水中會浮起來", lieElement.name); } }
相關連結:設計模式整理列表
沒有留言:
張貼留言