設計模式(21)---訪問者模式

1、定義ide

訪問者模式:表示一個做用於某對象結構中的各元素的操做。它使你能夠在不改變各元素的類的前提下定義做用與這些元素的新操做。this

解釋:一個對象,若是它的元素是固定的,那麼可使用訪問者模式定義它們的操做,使得操做能夠自由的增長或者減小而不影響系統的其它部分。spa

 

2、UML類圖及基本代碼code

基本代碼:對象

abstract class Visitor
    {
        public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
        public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
    }

    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);
        }
    }

    abstract class Element
    {
        public abstract void Accept(Visitor visitor);
    }

    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()
        { }
    }

    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);
            }
        }
    }

 

客戶端調用及其容許結果:blog

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);
View Code

 

3、實例說明接口

  介紹男人和女人之間的區別。如今元素包括男人和女人是固定的,可是它們的區別即操做很少種多樣的,例如:男人成功時,背後多半有一個偉大的女人,女人成功時,背後大多有一個不成功的男人;男人失敗時,悶頭喝酒,誰也不用勸,女人失敗時,眼淚汪汪,誰也勸不了,等等。代碼說明:element

 

首先編寫抽象人類和具體的對象男人、女人:it

abstract class Person
    {
        public abstract void Accept(Action action);
    }

    class Man : Person
    {
        public override void Accept(Action action)
        {
            action.GetManConclusion(this);
        }
    }

    class Woman : Person
    {
        public override void Accept(Action action)
        {
            action.GetWomanConclusion(this);
        }
    }

 

而後編寫元素的抽象操做類和具體的操做行爲:io

abstract class Action
    {
        public abstract void GetManConclusion(Man concreteElementA);
        public abstract void GetWomanConclusion(Woman concreteElementB);
    }

    class Success : Action
    {
        public override void GetManConclusion(Man concreteElementA)
        {
            Console.WriteLine("{0}{1}時,背後多半有一個偉大的女人", concreteElementA.GetType().Name, this.GetType().Name);
        }

        public override void GetWomanConclusion(Woman concreteElementB)
        {
            Console.WriteLine("{0}{1}時,背後大多有一個不成功的男人", concreteElementB.GetType().Name, this.GetType().Name);
        }
    }

    class Fail : Action
    {
        public override void GetManConclusion(Man concreteElementA)
        {
            Console.WriteLine("{0}{1}時,悶頭喝酒,誰也不用勸", concreteElementA.GetType().Name, this.GetType().Name);
        }

        public override void GetWomanConclusion(Woman concreteElementB)
        {
            Console.WriteLine("{0}{1}時,眼淚汪汪,誰也勸不了", concreteElementB.GetType().Name, this.GetType().Name);
        }
    }

 

最後編寫一個結構類,它枚舉元素,提供一個高層的接口以容許訪問者訪問它的元素

class ObjectStructure
    {
        private IList<Person> elements = new List<Person>();

        public void Attach(Person element)
        {
            elements.Add(element);
        }

        public void Detach(Person element)
        {
            elements.Remove(element);
        }

        public void Display(Action action)
        {
            foreach (Person e in elements)
            {
                e.Accept(action);
            }
        }
    }

 

客戶端調用及其結果:

ObjectStructure os = new ObjectStructure();
            os.Attach(new Man());
            os.Attach(new Woman());

            Success s = new Success();
            os.Display(s);

            Fail f = new Fail();
            os.Display(f);

 

4、優缺點及適用場景

優勢:

訪問者模式使得添加新的操做變得容易。若是一些操做依賴於一個複雜的結構對象的話,那麼通常而言,添加新的操做會變得很複雜。而使用訪問者模式,增長新的操做就意味着添加一個新的訪問者類。所以,使得添加新的操做變得容易。

缺點:

增長新的元素類變得困難。每增長一個新的元素意味着要在抽象訪問者角色中增長一個新的抽象操做,並在每個具體訪問者類中添加相應的具體操做。

 

適用場景:

說白了,就是能顯示其優勢迴避其缺點的地方均可以適用。

相關文章
相關標籤/搜索