using System;
using System.Collections;
// 抽象訪問者:針對每種具體元素宣告訪問方法
abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA e);
public abstract void VisitConcreteElementB(ConcreteElementB e);
}
// 具體訪問者 1
class ConcreteVisitor1 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA e)
=> Console.WriteLine($"{e} visited by {this}");
public override void VisitConcreteElementB(ConcreteElementB e)
=> Console.WriteLine($"{e} visited by {this}");
}
// 具體訪問者 2
class ConcreteVisitor2 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA e)
=> Console.WriteLine($"{e} visited by {this}");
public override void VisitConcreteElementB(ConcreteElementB e)
=> Console.WriteLine($"{e} visited by {this}");
}
// 抽象元素
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
// 具體元素 A
class ConcreteElementA : Element
{
public override void Accept(Visitor visitor) => visitor.VisitConcreteElementA(this);
public void OperationA() { }
}
// 具體元素 B
class ConcreteElementB : Element
{
public override void Accept(Visitor visitor) => visitor.VisitConcreteElementB(this);
public void OperationB() { }
}
// 物件結構
class ObjectStructure
{
private ArrayList elements = new ArrayList();
public void Attach(Element e) => elements.Add(e);
public void Detach(Element e) => elements.Remove(e);
public void Accept(Visitor visitor)
{
foreach (Element e in elements) e.Accept(visitor);
}
}
// 客戶端
public class Client
{
public static void Main()
{
ObjectStructure os = new ObjectStructure();
os.Attach(new ConcreteElementA());
os.Attach(new ConcreteElementB());
ConcreteVisitor1 v1 = new ConcreteVisitor1();
ConcreteVisitor2 v2 = new ConcreteVisitor2();
os.Accept(v1);
os.Accept(v2);
}
}
以 ConcreteElementA 接受 ConcreteVisitor1 為例:
ConcreteElementA.Accept(v1) 被調用,傳入 v1ConcreteElementA 反向調用 v1.VisitConcreteElementA(this),傳入自己v1 執行 ConcreteElementA.OperationA() 等業務邏輯**關鍵點**:元素主動將自己傳給訪問者,訪問者再根據元素具體類型調用對應方法——這就是「雙重分派」。
ObjectStructure 遍歷所有元素| 角色 | 類別 | 職責 |
|---|---|---|
| 抽象訪問者 | Visitor | 宣告所有具體元素的訪問介面 |
| 具體訪問者 | ConcreteVisitor1/2 | 實作各元素的具體訪問邏輯 |
| 抽象元素 | Element | 宣告 Accept(Visitor) 介面 |
| 具體元素 | ConcreteElementA/B | 實作 Accept,反向調用訪問者對應方法 |
| 物件結構 | ObjectStructure | 管理元素集合,提供遍歷接受訪問者 |