User-friendly design Model - The Visitor Pattern

Foreword

  Today we are looking at the visitor Visitor Pattern mode [  ], we understand that the name of the visitor pattern might be beneficial to our understanding of its core code block. We see such an example: I went to a friend's house guest, then a friend belong to the owner, I belong to the visitor. Then just a friend in cooking, but can not get soy sauce. If a friend go buy soy sauce will be very cumbersome and will affect the cooking. Then I went to run for the visitors. He ran quickly out the name of the sauce on the back. It is simple to understand, visitors on the basis of the original owner to help the owner to accomplish something inconvenient or able to fulfill the owner.

Visitors introduction mode

First, the reason

  In software system development, we often meet some hierarchy intact because the code needs to change and change. You say this time I change the base class it, all subclasses must change, this is a very troublesome thing. So I can not change the modifications are complete new demand it under the premise of full hierarchy?

Second, the intent

  It represents an operation object structure of the role each element. It can not change the definition of the class action under the premise of each element in the new operating these elements.

Third, the case of FIG.

Fourth, the visitor pattern code sample

See chart above case can be found in the visitor pattern contains the following sections:

Structure objects: a container of nodes, comprising a plurality of class or interface to abstract node: declare a receiving operation, receiving the visitor object as a parameter, processing interface declaration, the data processing nodes

Specific Node: implementation of the abstract node receiving operation and processing operations

Visitors abstract: declare one or more access operations, so that all visitors must implement specific

Specific Visitors: implementation of the abstract interface declaration visitors

We see such a demand, we need to calculate the area of ​​graphics and output, including graphic rectangle round. We take a look at the code to achieve it:

  First, we do not see using the Visitor pattern implementation:

namespace Visitor_Pattern
{
    class VisitorPattern
    {
    }

    ///  <Summary> 
    /// abstract node class
     ///  </ Summary> 
    public  abstract  class the Element
    {
       public  abstract  void CalculatedArea ();
    }

    ///  <Summary> 
    /// rectangular area calculated output
     ///  </ Summary> 
    public  class the Rectangle: the Element
    {
        public double _long;
        public double _wide;

        public  Rectangle(double Long, double Wide) 
        {
            this._long = Long;
            this._wide = Wide;
        }
        public  override  void CalculatedArea ()
        {
            Console.WriteLine ($ " rectangular area is: _wide} * {_ Long " );
        }
    }

    ///  <Summary> 
    /// circular area is calculated output
     ///  </ Summary> 
    public  class Circular: the Element
    {
        public double _r; 

        public Circular(double r)
        {
            this._r = r; 
        }
        public  override  void CalculatedArea ()
        {
            Console.WriteLine ($ " area of a circle is: the _r * * Math.PI the _r {} " );
        }
    }

    ///  <Summary> 
    /// structural object
     ///  </ Summary> 
    public  class the Graphical
    {
        public List<Element> elements = new List<Element>();
        public List<Element> Elements
        {
            get { return elements; }
        }

        public Graphical() 
        {
            Element element = new Rectangle(10,5);
            Element element1= new Circular(5);
            elements.Add(element);
            elements.Add(element1);
        }
    }
}

 

namespace Visitor_Pattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Graphical graphical = new Graphical();
            foreach (var item in graphical.Elements)
            {
                item.CalculatedArea();
            }

        }
    }
}

 

  We can see that it is relatively simple to achieve. But if there were changes in demand, the need to add girth and graphics output, while its output parameters. This trouble. We need to make changes to the base class and modify the subclass. I feel a bit more harm than good.

  We look at the use of models to achieve:

namespace Visitor_Pattern
{
    class UseVisitorPattern
    {
    }

    #region visitors

    ///  <the Summary> 
    /// abstract visitors
     ///  </ the Summary> 
    public  interface IVistor
    {
        void Visit(UseRectangle rectangle);
        void Visit(UseCircular  useCircular);
    }

    ///  <Summary> 
    /// DETAILED visitor
     ///  </ Summary> 
    public  class Vistor: IVistor
    {
        public void Visit(UseRectangle rectangle)
        {
            rectangle.CalculatedArea();
            Console.WriteLine ($ " rectangular length is: rectangle._long {} " );
            Console.WriteLine ($ " rectangle is wide: rectangle._wide {} " );
            Console.WriteLine ($ " rectangular perimeter is: {2 * (+ rectangle._long rectangle._wide)} " );
        }

        public void Visit(UseCircular useCircular)
        {
            useCircular.CalculatedArea();
            Console.WriteLine ($ " radius of the circle is: useCircular._r {} " );
            Console.WriteLine ($ " circular perimeter yes: * {2 * Math.PI useCircular._r} " );
        }
    }

    #endregion

    #region node class

    ///  <Summary> 
    /// abstract node class
     ///  </ Summary> 
    public  abstract  class UseElement
    {
        public abstract void Accept(IVistor vistor);
        public abstract void CalculatedArea();
    }

    ///  <Summary> 
    /// rectangular area calculated output
     ///  </ Summary> 
    public  class UseRectangle: UseElement
    {
        public double _long;
        public double _wide;

        public UseRectangle(double Long, double Wide)
        {
            this._long = Long;
            this._wide = Wide;
        }

        public override void Accept(IVistor vistor)
        {
            vistor.Visit(this);
        }

        public  override  void CalculatedArea ()
        {
            Console.WriteLine ($ " rectangular area is: _wide} * {_ Long " );
        }
    }

    ///  <Summary> 
    /// circular area is calculated output
     ///  </ Summary> 
    public  class UseCircular: UseElement
    {
        public double _r;

        public UseCircular(double r)
        {
            this._r = r;
        }
        public override void Accept(IVistor vistor)
        {
            vistor.Visit(this);
        }
        public  override  void CalculatedArea ()
        {
            Console.WriteLine ($ " area of a circle is: the _r * * Math.PI the _r {} " );
        }
    }

    #endregion

    ///  <Summary> 
    /// structural object
     ///  </ Summary> 
    public  class UseGraphical
    {
        public List<UseElement> elements = new List<UseElement>();
        public List<UseElement> Elements
        {
            get { return elements; }
        }

        public UseGraphical()
        {
            UseElement element = new UseRectangle(10, 5);
            UseElement element1 = new UseCircular(5);
            elements.Add(element);
            elements.Add(element1);
        }
    }
}

 

namespace Visitor_Pattern
{
    class Program
    {
        static void Main(string[] args)
        {

            UseGraphical graphical = new UseGraphical();
            foreach (var item in graphical.Elements)
            {
                item.Accept(new Vistor());
            }
        }
    }
}

  Here we have joined the visitors to each node, we demand changes to increase the output parameters of the perimeter and when specific modifications to increase the visitor can be achieved.

Usage scenarios and the advantages and disadvantages

First, the use of scenarios

1, the object corresponding to the object class structure change less, but will often define a new operation on this object structure

2, needs to be unrelated to the operation of the structure of an object, the need to avoid altering its original new class during operation

Second, the advantage

1, in line with the principle of single responsibility. Each class is responsible for a duty

2, with excellent scalability and flexibility to add new operations will become easier, but also will not change the original structure of the code

3, the operation mode of collection of visitors associated visitor behavior of the object, its elements and not dispersed in the class

Third, shortcomings

1, the specific elements of the visitor disclose details, contrary to the principle of Demeter

2, increasing the specific element node becomes difficult, with increases in visitor is new.

to sum up

  Visitor pattern described here friends. The main visitor pattern is a data structure and operation of separation, the solution stable and easily change the data structure of the coupling operation. It does not modify the original structure of the object class in the new operation time. Visitors to directly modify the operation of the object to add the operation.


      If we want more roses, we must plant more roses tree.

     C # Design Patterns series directory

        Welcome to scan the next Fanger Wei code, and I set foot on the road to pass through the design patterns it!

  

 

Guess you like

Origin www.cnblogs.com/hulizhong/p/11704390.html