1. 程式人生 > >【設計模式】——訪問者模式

【設計模式】——訪問者模式

【訪問者模式】

 

訪問者模式(Visitor),表示一個作用於某物件結構中的各元素的操作。它使你可以在不改變個元素的類的前提下定義作用於這些元素的新操作

 

【介紹】

 

  • 主要解決:穩定的資料結構和易變的操作耦合問題

  • 何時使用:需要對一個物件結構中的物件進行很多不同的並且不相關的操作,而需要避免這些操作影響到這些物件的類

  • 如何解決:在被訪問者的類裡面加一個對外提供接待訪問者的介面

  • 關鍵程式碼:在資料基礎類裡面有一個方法接受訪問者,將自身引用傳入訪問者

  • 優點:符合單一職責原則;優秀的擴充套件性;靈活性

  • 缺點:具體元素對訪問者公佈細節,違反了迪米特法則;具體元素變更比較困難;違反了依賴倒置原則,依賴了具體類,沒有依賴抽象

  • 注意事項:訪問者可以對功能進行統一

 

【實現】

 


步驟一:Element類:人類

 abstract class Person

    {

        //接受

        public abstract void Accept(Action visitor);

    }

步驟二:ConcreteCisitor類:具體人類

 

//男人

    class Man : Person

    {

        public override void Accept(Action visitor)

        {

            visitor.GetManConclusion(this);

        }

    }



    //女人

    class Woman : Person

    {

        public override void Accept(Action visitor)

        {

            visitor.GetWomanConclusion(this);

        }

    }




 

步驟三:Visitor類:狀態類

abstract class Action

    {

        //得到男人結論或反應

        public abstract void GetManConclusion(Man concreteElementA);

        //得到女人結論或反應

        public abstract void GetWomanConclusion(Woman concreteElementB);

    }

 

步驟四:ConcreteCisitor類:具體狀態類

 

  //成功

    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 Failing : 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 Amativeness : 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 Marriage : 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);

        }

    }


  
步驟五:ObjectStructure類:物件結構類

 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 visitor)

        {

            foreach (Person e in elements)

            {

                e.Accept(visitor);

            }

        }

    }



步驟六:客戶端程式碼


 

static void Main(string[] args)

        {

            ObjectStructure o = new ObjectStructure();

            o.Attach(new Man());

            o.Attach(new Woman());



            Success v1 = new Success();

            o.Display(v1);



            Failing v2 = new Failing();

            o.Display(v2);



            Amativeness v3 = new Amativeness();

            o.Display(v3);



            Marriage v4 = new Marriage();

            o.Display(v4);



            Console.Read();

        }



【總結】

 

一、訪問者模式的目的是要把處理從資料結構分離出來,讓系統又比較穩定的資料結構,有易於變化的演算法,使得演算法操作的增加變得容易

 

二、訪問者模式增加新的操作很容易,因為增加新的操作就意味著增加一個新的訪問者,訪問者模式將有關的行為集中到一個訪問者物件中