最複雜的設計模式---訪問者模式

        今天,我們一起來探討最後一個、最複雜的設計模式 訪問者模式;它表示一個作用於某個對象結構中的各個元素的操作。它使你可以在不改變個元素的類前提下,定義作用於這些元素的新操作。這個地方要注意: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);
		}
	}
}


客戶端代碼,先組裝元素,然後定義訪問狀態,進行訪問;如果我們需要新增加操作,只需要繼承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);
}
      好了,現在想想啥時候我們用這種模式?一般在數據結構相對比較穩定的時候,我們採用此模式進行編碼;這種模式最大的好處在於把數據結構和作用於上的操作直接耦合性降低了;方便我們新增對元素的操作;但是這個設計模式也有弊端:要求數據結構元素的類型必須相對穩定。


      

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章