访问者模式

发布时间 2023-06-03 21:28:33作者: 云霄宇霁

    The Visitor design pattern represents an operation to be peformed on the elements of object structure. This pattern lets you define a new operation without changing the classes of the elements on which it operates.

访问者模式表示要对对象结构的元素执行的操作。此模式允许你定义新操作,而无需要更改其操作的元素的类。

The Visitor pattern in which an object traverses an object structure and performs the same operation on each mode in this structure. Different visitor objects define different operations.

In the Visitor Design Pattern, we use a Visitor object which changes the excuting algorithm of an element object. In this way, when the visitor varies, the excution algorithm of the elment object can also vary. As per the Visitor Design Pattern, the element object has to accept the visitor object so that the visitor objedct handles the operation on the elment object.

 UML Class Diagram

Visitor: This is going to be an interface or abstract class and it declares the Visit operation for each element in the object structure.

ConcreteVisitor: These are the subclasses that implement each operation declared by the IVisitor interface or override the abstract method of the class. Each operation implements a fragment of the algorithm defined for the corresponding class or  object in the structure.

Element: This is an interface or abstract class that defines an Accept operation that takes a vistor as an argument.

ConcreteElement: This is a class that implements the Element interface or override the abstract method i.e. this class implements the Accept operation that takes a visitor as an argument.

ObjectStructure: This is a class that holds all the elments and provides a high-level interface that allows the visitor to visit all the elements.

Client: This is a class that has  access to the data structure objects and can instruct them to accept a Visitor to perform the appropriate operation. 

 

Structure Code IN C#

 /// <summary>
    /// The Visitor Interface declares the Visit Method that corresponds to the Elment class.
    /// The Visit Method will accept the IElement object as a parameter i.e. the concrete class.
    /// </summary>
    public interface IVisitor
    {
        void Visit(IElement element);
    }

    /// <summary>
    /// Concrete Visitors implement serveral versions of the same algorithm, which can work with all concrete component class.
    /// The following Concrete Visitor class implements the Visit Method declared by Visitor Interface.
    /// The Visit Method implements a fragement of the algorithm defined for the corresponding Element class.
    /// </summary>
    public class ConcreteVisitorA : IVisitor
    {
        public void Visit(IElement element)
        {
            Console.WriteLine($"{typeof(ConcreteVisitorA).Name} visit {element.Name}.");
        }
    }

    public class ConcreteVisitorB : IVisitor
    {
        public void Visit(IElement element)
        {
            Console.WriteLine($"{typeof(ConcreteVisitorB).Name} visit {element.Name}.");
        }
    }
Visitor
 /// <summary>
    /// The element interface declares an Accept Method that should take the base visitor interface as an argument.
    /// </summary>
    public interface IElement
    {
        string Name { get; set; }
        void Accept(IVisitor vistor);
    }

    /// <summary>
    /// The Concrete Element implements the Accept operation that takes a Visitor as an argument.
    /// </summary>
    public class ElementA : IElement
    {
        private string _name;
        string IElement.Name
        { 
            get => _name; 
            set => _name = value; 
        }

        public ElementA(string name)
        {
            _name = name;
        }

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

    public class ElementB : IElement
    {
        private string _name;
        string IElement.Name
        {
            get => _name;
            set => _name = value;
        }

        public ElementB(string name)
        {
            _name = name;
        }

        public void Accept(IVisitor vistor)
        {
            vistor.Visit(this);
        }
    }
Element
/// <summary>
    /// Object Structure
    /// The ObjectStructure contains the list of elements that a visitor wants to visit.
    /// </summary>
    public class ObjectStructure 
    {
        public List<IElement> elements = new List<IElement>();
        public void Attach(IElement element)
        {
            elements.Add(element);  
        }
        public void Detach(IElement element) 
        {
            elements.Remove(element);
        }
        public void Operate(IVisitor visitor)
        {
            foreach (var element in elements)
            {
                visitor.Visit(element);
            }
        }
    }
Structure
var structure = new ObjectStructure();
structure.Attach(new ElementA("A01"));
structure.Attach(new ElementA("A02"));
structure.Attach(new ElementB("B01"));
structure.Attach(new ElementB("B02"));
structure.Operate(new ConcreteVisitorA());
structure.Operate(new ConcreteVisitorB());
Client

 

When to use Vistor Design Pattern In C#?

  • An object structure must have many unrelated operations to perform on it.
  • An object structure cannot change but operations performed on it can change.
  • The operations need to perform on the concrete classes of an object structure.
  • Exposing the internal state or operations of the object structure is acceptable.
  • Operations shoud be able to operate on multiple object structures that implement the same interface.