設計模式筆記(24)---訪問者模式(行為型)


Gof定義

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

動機

在軟件構建過程中,由於需求的改變,某些類層次結構中常常需要增加新的行為(方法),如果直接在基類中做這樣的更改,將會給子類帶來很繁重的變更負擔,甚至破壞原有設計。如何在不更改類層次結構的前提下,在運行時根據需要透明地為類層次結構上的各個類動態添加新的操作,從而避免上述問題?請看下面訪問者模式結構圖和代碼。

訪問者模式結構圖:

2010-01-31_221419

基本代碼如下:

/// <summary>
/// 聲明了一個或多個需要添加的操作
/// </summary>
public abstract class Visitor
{
    public abstract void VisitorConcreteElementA(ConcreteElementA concreteElementA);
    public abstract void VisitorConcreteElementB(ConcreteElementB concreteElementB);
}
/// <summary>
/// 操作的具體類1
/// </summary>
public class ConcreteVisitor1:Visitor
{
    public override void VisitorConcreteElementA(ConcreteElementA concreteElementA)
    {
        Console.WriteLine("{0}訪問{1}", this.GetType().Name, concreteElementA.GetType().Name);
    }
    public override void VisitorConcreteElementB(ConcreteElementB concreteElementB)
    {
        Console.WriteLine("{0}訪問{1}", this.GetType().Name, concreteElementB.GetType().Name);
    }
}
/// <summary>
/// 操作的具體類2
/// </summary>
public class ConcreteVisitor2 : Visitor
{
    public override void VisitorConcreteElementA(ConcreteElementA concreteElementA)
    {
        Console.WriteLine("{0}訪問{1}", this.GetType().Name, concreteElementA.GetType().Name);
    }
    public override void VisitorConcreteElementB(ConcreteElementB concreteElementB)
    {
        Console.WriteLine("{0}訪問{1}", this.GetType().Name, concreteElementB.GetType().Name);
    }
}
/// <summary>
/// 接受Visitor並使用其操作的抽象類
/// </summary>
public abstract class Element
{
    public abstract void Accept(Visitor visitor);
}
/// <summary>
/// 接受Visitor並使用其操作的具體類
/// </summary>
public class ConcreteElementA : Element
{
    public override void Accept(Visitor visitor)
    {
        visitor.VisitorConcreteElementA(this);
    }
    public void OperationA() { }
}
/// <summary>
/// 接受Visitor並使用其操作的具體類
/// </summary>
public class ConcreteElementB : Element
{
    public override void Accept(Visitor visitor)
    {
        visitor.VisitorConcreteElementB(this);
    }
    public void OperationB() { }
}
public class ObjectStructure
{
    private List<Element> list = new List<Element>();
    public void Add(Element element)
    {
        list.Add(element);
    }
    public void Del(Element element)
    {
        if(list.Contains(element))
            list.Remove(element);
    }
    public void Accept(Visitor visitor)
    {
        foreach (Element e in list)
        {
            e.Accept(visitor);
        }
    }
}
/// <summary>
/// 客戶端代碼
/// </summary>
class Program
{
    static void Main(string[] args)
    {
        ObjectStructure os = new ObjectStructure();
        os.Add(new ConcreteElementA());
        os.Add(new ConcreteElementB());
        Visitor cv1 = new ConcreteVisitor1();
        Visitor cv2 = new ConcreteVisitor2();
        os.Accept(cv2);
        os.Accept(cv1);
    }
}

Visitor模式的幾個要點

  • Visitor模式通過所謂雙重分發(double dispatch)來實現在不更改Element類層次結構的前提下,在運行時透明地為類層次結構上的各個類動態添加新的操作。
  • Visitor模式通過所謂雙重分發(double dispatch)來實現在不更改Element類層次結構的前提下,在運行時透明地為類層次結構上的各個類動態添加新的操作。
  • Visitor模式的最大缺點在於擴展類層次結構(增添新的Element子類),會導致Visitor類的改變。因此Vistor模式適用於“Element類層次結構穩定,而其中的操作卻經常面臨頻繁改動”。

 

返回開篇(索引)


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com