設計模式之訪問者模式

訪問者模式: 使用一個訪問者類,改變元素類的執行算法。通過這種方式,元素的執行算法可以隨着訪問者改變而改變。這種類型的設計模式屬於行爲型模式。

主要意圖:主要將數據結構與數據操作分離。

主要解決:穩定的數據結構和易變的操作耦合問題。

解決方案:在被訪問的類裏面加一個對外提供接待訪問者的接口。

優點:

1,各角色職責分離,符合單一職責原則。

2,具有優秀的擴展性。

3,使得數據結構和作用於結構上的操作解耦,使得操作集合可以獨立變化。

4,靈活性。

缺點:

1,具體元素對訪問者公佈細節,違反了迪米特原則。

2,具體元素變更時導致修改成本大。

3,違反了依賴倒置原則,爲了達到“區別對待”而依賴了具體類,沒有以來抽象。,

訪問者模式類圖:

代碼實現:

客戶端代碼:

using System;

namespace _03訪問者模式_基礎版
{
    class Program
    {
        static void Main(string[] args)
        {
            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);

            Console.Read();
        }
    }
}

接口(抽象類):

using System;
using System.Collections.Generic;
using System.Text;

namespace _03訪問者模式_基礎版
{
    abstract class Visitor
    {
        public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
        public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
    }
}

具體的訪問者:

using System;
using System.Collections.Generic;
using System.Text;

namespace _03訪問者模式_基礎版
{
    class ConcreteVisitor1:Visitor
    {
        public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
        {
            Console.WriteLine("{0}被{1}訪問",concreteElementA.GetType().Name,this.GetType().Name);
        }
        public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
        {
            Console.WriteLine("{0}被{1}訪問",concreteElementB.GetType().Name,this.GetType().Name);
        }
    }
    class ConcreteVisitor2:Visitor
    {
        public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
        {
            Console.WriteLine("{0}被{1}訪問", concreteElementA.GetType().Name, this.GetType().Name);
        }
        public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
        {
            Console.WriteLine("{0}被{1}訪問", concreteElementB.GetType().Name, this.GetType().Name);
        }
    }
}

元素接口或者抽象類:

using System;
using System.Collections.Generic;
using System.Text;

namespace _03訪問者模式_基礎版
{
    abstract class Element
    {
        public abstract void Accept(Visitor visitor);
    }
}

具體的元素類

using System;
using System.Collections.Generic;
using System.Text;

namespace _03訪問者模式_基礎版
{
    class ConcreteElementA:Element
    {
        public override void Accept(Visitor visitor)
        {
            visitor.VisitConcreteElementA(this);
        }
        public void OperationA()
        { }
    }
    class ConcreteElementB:Element
    {
        public override void Accept(Visitor visitor)
        {
            visitor.VisitConcreteElementB(this);
        }
        public void OperationB()
        { }
    }
}

對象結構:

using System;
using System.Collections.Generic;
using System.Text;

namespace _03訪問者模式_基礎版
{
    class ObjectStructure
    {
        private IList<Element> elements = new List<Element>();
        public void Attach(Element element)
        {
            elements.Add(element);
        }
        public void Detach(Element element)
        {
            elements.Remove(element);
        }
        public void Accept(Visitor visitor)
        {
            foreach(Element e in elements)
            {
                e.Accept(visitor);
            }
        }
    }
}

總結:

我們要根據具體情況來評估是否適合使用訪問者模式,例如,我們的對象結構是否足夠穩定,是否需要經常定義新的操作,使用訪問者模式是否能優化我們的代碼,而不是使我們的代碼變得更復雜。

發佈了50 篇原創文章 · 獲贊 0 · 訪問量 2645
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章