今天,我們一起來探討最後一個、最複雜的設計模式 訪問者模式;它表示一個作用於某個對象結構中的各個元素的操作。它使你可以在不改變個元素的類前提下,定義作用於這些元素的新操作。這個地方要注意:1.需要有個對象結構類用於存儲循環遍歷的方法的方式;2.訪問者模式是對元素的操作;3.可以任意添加對這些元素的新操作。確實有點複雜,我們先看看其結構圖:
代碼部分:
Visitor類抽象聲明瞭對各種類型元素的訪問方法;
abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA elementA);
public abstract void VisitConcreteElementB(ConcreteElementB elementB);
}
ConcreteVisitor1 和ConcreteVisitor2 分別定義兩種不同訪問狀態下的對各種元素的實際操作;
class ConcreteVisitor1:Visitor
{
public override void VisitConcreteElementA(ConcreteElementA elementA)
{
Console.WriteLine("1元素{0}被{1}訪問",elementA.GetType().Name,this.GetTye().name);
}
public override void VisitConcreteElementB(ConcreteElementB elementB)
{
Console.WriteLine("1元素{0}被{1}訪問",elementB.GetType().Name,this.GetTye().name);
}
}
class ConcreteVisitor2:Visitor
{
public override void VisitConcreteElementA(ConcreteElementA elementA)
{
Console.WriteLine("2元素{0}被{1}訪問",elementA.GetType().Name,this.GetTye().name);
}
public override void VisitConcreteElementB(ConcreteElementB elementB)
{
Console.WriteLine("2元素{0}被{1}訪問",elementB.GetType().Name,this.GetTye().name);
}
}
Element是對元素的抽象類,聲明瞭元素根據傳入的訪問狀態進行的操作方法;
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
具體的元素類:ConcreteElementA、ConcreteElementB ;具體的定義了元素訪問方式;這個地方我們要提到二次分派的技術。什麼是二次分派?就是先方法狀態以參數的形式傳輸給具體的元素類,然後又根據傳入的訪問狀態的方法並將自身以參數的形式傳入;
class ConcreteElementA : Element
{
public override void Accept(Visitor visitor)
{
//這個地方用藥2次分派的技術,讓操作與數據結構的分離
visitor.VisitConcreteElementA(this);
}
//其他方法的定義
public void OperationA()
{
}
}
class ConcreteElementB : Element
{
public override void Accept(Visitor visitor)
{
//這個地方用藥2次分派的技術,讓操作與數據結構的分離
visitor.VisitConcreteElementB(this);
}
//其他方法的定義
public void OperationB()
{
}
}
class ObjectStructure
{
private IList<Element> list=new List<Element>();
public void Attach(Element element)
{
list.Add(element);
}
public void Detach(Element element)
{
list.Delete(element);
}
public void Accept(Visitor visitor)
{
foreach(Element a in list)
{
a.Accept(visitor);
}
}
}
static void Main(string[] arg)
{
ObjectStructure o=new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());
ConcreteVisitor1 v1=new ConcreteVisitor1();
ConcreteVisitor2 v2=new ConcreteVisitor2();
o.Accept(v1);
o.Accept(v2);
//如果新增加操作則如以下代碼
//ConcreteVisitor3 v3=new ConcreteVisitor3();
//o.Accept(v3);
}
好了,現在想想啥時候我們用這種模式?一般在數據結構相對比較穩定的時候,我們採用此模式進行編碼;這種模式最大的好處在於把數據結構和作用於上的操作直接耦合性降低了;方便我們新增對元素的操作;但是這個設計模式也有弊端:要求數據結構元素的類型必須相對穩定。