C++ Visitor Pattern of Design Pattern 23 (including sample code)

The visitor pattern is a behavioral design pattern that defines new operations on existing objects without changing the structure of these objects.

Here is a sample code implementing the visitor pattern in C++:

#include <iostream>
#include <vector>
// 前向声明
class ConcreteElementA;
class ConcreteElementB;
// 抽象访问者:定义了对各种具体元素进行访问的接口
class Visitor {
    
    
public:
    virtual ~Visitor() {
    
    }
    virtual void VisitConcreteElementA(ConcreteElementA* concrete_element_a) = 0;
    virtual void VisitConcreteElementB(ConcreteElementB* concrete_element_b) = 0;
};
// 具体访问者:实现了抽象访问者定义的接口,对各种具体元素进行访问
class ConcreteVisitor1 : public Visitor {
    
    
public:
    virtual void VisitConcreteElementA(ConcreteElementA* concrete_element_a) override {
    
    
        std::cout << "Concrete Visitor 1: visit Concrete Element A" << std::endl;
    }
    virtual void VisitConcreteElementB(ConcreteElementB* concrete_element_b) override {
    
    
        std::cout << "Concrete Visitor 1: visit Concrete Element B" << std::endl;
    }
};
class ConcreteVisitor2 : public Visitor {
    
    
public:
    virtual void VisitConcreteElementA(ConcreteElementA* concrete_element_a) override {
    
    
        std::cout << "Concrete Visitor 2: visit Concrete Element A" << std::endl;
    }
    virtual void VisitConcreteElementB(ConcreteElementB* concrete_element_b) override {
    
    
        std::cout << "Concrete Visitor 2: visit Concrete Element B" << std::endl;
    }
};
// 抽象元素:定义了一个 Accept 操作,接受一个访问者对象作为参数
class Element {
    
    
public:
    virtual ~Element() {
    
    }
    virtual void Accept(Visitor* visitor) = 0;
};
// 具体元素:实现了抽象元素定义的接口,实现了 Accept 操作
class ConcreteElementA : public Element {
    
    
public:
    virtual void Accept(Visitor* visitor) override {
    
    
        visitor->VisitConcreteElementA(this);
    }
};
class ConcreteElementB : public Element {
    
    
public:
    virtual void Accept(Visitor* visitor) override {
    
    
        visitor->VisitConcreteElementB(this);
    }
};
// 对象结构:包含了一组具体元素对象,可以被访问者访问
class ObjectStructure {
    
    
public:
    void AddElement(Element* element) {
    
    
        elements_.push_back(element);
    }
    void RemoveElement(Element* element) {
    
    
        // 省略删除元素的代码
    }
    void Accept(Visitor* visitor) {
    
    
        for (auto element : elements_) {
    
    
            element->Accept(visitor);
        }
    }
private:
    std::vector<Element*> elements_;
};
int main() {
    
    
    // 创建对象结构和访问者对象
    ObjectStructure object_structure;
    ConcreteVisitor1 concrete_visitor1;
    ConcreteVisitor2 concrete_visitor2;
    // 向对象结构中添加具体元素对象
    object_structure.AddElement(new ConcreteElementA);
    object_structure.AddElement(new ConcreteElementB);
    // 让访问者1访问对象结构中的元素
    object_structure.Accept(&concrete_visitor1);
    // 输出 "Concrete Visitor 1: visit Concrete Element A" 和 "Concrete Visitor 1: visit Concrete Element B"
    // 让访问者2访问对象结构中的元素
    object_structure.Accept(&concrete_visitor2);
    // 输出 "Concrete Visitor 2: visit Concrete Element A" 和 "Concrete Visitor 2: visit Concrete Element B"
    return 0;
}

In the above code, we first define an abstract visitor Visitor, which defines the interface for accessing various concrete elements. Next, we created two specific visitors, ConcreteVisitor1 and ConcreteVisitor2, which implement the interface defined in Visitor and visit various specific elements.

In Element, we define an Accept() operation that accepts a visitor object as a parameter. The specific elements ConcreteElementA and ConcreteElementB implement the interface defined in Element and implement the Accept() operation.

In ObjectStructure, we include a set of concrete element objects that can be accessed by visitors. Finally, in the main() function, we create the object structure and the visitor object, add specific element objects to the object structure, let the visitor access the elements in the object structure, and output the result of the visit.

The advantage of the visitor pattern is that it allows defining new operations on existing objects without changing the structure of these objects. By separating the operation of the visitor, we can implement different operations on different elements, which increases the flexibility and scalability of the code. However, the visitor pattern may also lead to an increase in the complexity of the code, because we need to define the visitor interface, concrete visitors and abstract elements, thus increasing the amount of code.

Guess you like

Origin blog.csdn.net/dica54dica/article/details/130021679