访问者模式(Visitor Pattern)是一种行为设计模式,它允许你将算法 与对象结构分离,使得可以在不修改现有对象结构的情况下定义新的操作。
核心概念
设计原则
访问者模式遵循以下设计原则:
- 
开闭原则:可以添加新访问者而不修改元素类 
- 
单一职责原则:将相关行为集中到访问者中 
- 
双重分发:利用双分派技术实现动态绑定 
主要优点
- 
算法集中:将相关行为集中在一个访问者对象中 
- 
灵活扩展:容易添加新的操作 
- 
跨类操作:可以对不同类的对象执行统一操作 
- 
数据分离:将数据结构与数据操作分离 
模式结构
主要组件
- 
Visitor(访问者接口) - 为每个具体元素类声明访问操作
 
- 
ConcreteVisitor(具体访问者) - 实现每个访问操作
 
- 
Element(元素接口) - 定义accept方法接受访问者
 
- 
ConcreteElement(具体元素) - 实现accept方法
 
- 
ObjectStructure(对象结构) - 
维护元素集合 
- 
提供遍历元素的方法 
 
- 
完整代码示例
#include <iostream>
#include <vector>
#include <memory>
#include <string>
// 前向声明
class ConcreteElementA;
class ConcreteElementB;
// ==================== 访问者接口 ====================
class Visitor {
public:
    virtual void visit(ConcreteElementA* element) = 0;
    virtual void visit(ConcreteElementB* element) = 0;
    virtual ~Visitor() = default;
};
// ==================== 元素接口 ====================
class Element {
public:
    virtual void accept(Visitor* visitor) = 0;
    virtual ~Element() = default;
};
// ==================== 具体元素A ====================
class ConcreteElementA : public Element {
    std::string name_;
public:
    explicit ConcreteElementA(const std::string& name) : name_(name) {}
    
    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }
    
    std::string getName() const { return name_; }
    
    // 元素特有的操作
    std::string operationA() const {
        return "元素A特有操作";
    }
};
// ==================== 具体元素B ====================
class ConcreteElementB : public Element {
    int value_;
public:
    explicit ConcreteElementB(int value) : value_(value) {}
    
    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }
    
    int getValue() const { return value_; }
    
    // 元素特有的操作
    std::string operationB() const {
        return "元素B特有操作";
    }
};
// ==================== 具体访问者1 ====================
class ConcreteVisitor1 : public Visitor {
public:
    void visit(ConcreteElementA* element) override {
        std::cout << "访问者1访问" << element->getName() 
                  << ": " << element->operationA() << std::endl;
    }
    
    void visit(ConcreteElementB* element) override {
        std::cout << "访问者1访问元素B(值=" << element->getValue() 
                  << "): " << element->operationB() << std::endl;
    }
};
// ==================== 具体访问者2 ====================
class ConcreteVisitor2 : public Visitor {
public:
    void visit(ConcreteElementA* element) override {
        std::cout << "访问者2记录元素A: " << element->getName() << std::endl;
    }
    
    void visit(ConcreteElementB* element) override {
        std::cout << "访问者2处理元素B值: " 
                  << element->getValue() * 2 << std::endl;
    }
};
// ==================== 对象结构 ====================
class ObjectStructure {
    std::vector<std::unique_ptr<Element>> elements_;
    
public:
    void addElement(std::unique_ptr<Element> element) {
        elements_.push_back(std::move(element));
    }
    
    void accept(Visitor* visitor) {
        for (const auto& element : elements_) {
            element->accept(visitor);
        }
    }
};
// ==================== 客户端代码 ====================
int main() {
    std::cout << "=== 访问者模式演示 ===" << std::endl;
    
    // 创建对象结构
    ObjectStructure structure;
    structure.addElement(std::make_unique<ConcreteElementA>("测试元素A"));
    structure.addElement(std::make_unique<ConcreteElementB>(42));
    structure.addElement(std::make_unique<ConcreteElementA>("另一个元素A"));
    structure.addElement(std::make_unique<ConcreteElementB>(100));
    
    // 创建访问者
    ConcreteVisitor1 visitor1;
    ConcreteVisitor2 visitor2;
    
    // 使用不同访问者访问结构
    std::cout << "\n使用访问者1:" << std::endl;
    structure.accept(&visitor1);
    
    std::cout << "\n使用访问者2:" << std::endl;
    structure.accept(&visitor2);
    
    return 0;
}模式变体
1. 带返回值的访问者
class ComputingVisitor : public Visitor {
    int total_ = 0;
public:
    void visit(ConcreteElementA* element) override {
        total_ += element->getName().length();
    }
    
    void visit(ConcreteElementB* element) override {
        total_ += element->getValue();
    }
    
    int getTotal() const { return total_; }
};
// 使用示例
ComputingVisitor computingVisitor;
structure.accept(&computingVisitor);
std::cout << "计算总和: " << computingVisitor.getTotal() << std::endl;2. 基于模板的访问者
template <typename... Types>
class GenericVisitor;
template <typename T>
class GenericVisitor<T> {
public:
    virtual void visit(T* element) = 0;
    virtual ~GenericVisitor() = default;
};
template <typename T, typename... Types>
class GenericVisitor<T, Types...> : public GenericVisitor<Types...> {
public:
    using GenericVisitor<Types...>::visit;
    virtual void visit(T* element) = 0;
};
// 定义元素接口
class Element {
public:
    template <typename... Types>
    void accept(GenericVisitor<Types...>* visitor) {
        if (auto* v = dynamic_cast<GenericVisitor<ConcreteElementA, ConcreteElementB>*>(visitor)) {
            if (auto* elem = dynamic_cast<ConcreteElementA*>(this)) {
                v->visit(elem);
            } else if (auto* elem = dynamic_cast<ConcreteElementB*>(this)) {
                v->visit(elem);
            }
        }
    }
};实际应用场景
- 
编译器设计:语法树的不同遍历方式(类型检查、代码生成等) 
- 
文档处理:对文档结构的不同操作(渲染、字数统计等) 
- 
UI组件:对复杂UI结构的操作(样式应用、布局计算等) 
- 
游戏开发:游戏对象的不同处理(渲染、物理计算等) 
- 
财务系统:财务数据的不同分析(税务计算、报表生成等)