汇总目录请点击访问:《设计模式目录汇总》
喜欢内容的话欢迎关注、点赞、收藏!感谢支持,祝大家祉猷并茂,顺遂无虞!
访问者模式详解
概念
访问者模式(Visitor Pattern)是一种行为型设计模式,用于将数据结构与其操作解耦。通过在不改变数据结构的前提下,增加新的操作,访问者模式提供了一种灵活的方式来实现功能扩展。
关键特性
- 分离操作:将具体操作从对象本身分离,使得操作逻辑集中在访问者中。
- 支持扩展:容易增加新的操作,但增加新的数据结构时会比较复杂。
- 双分派机制:通过在访问者和元素之间的双向调用实现。
适用场景
- 需要对对象结构中的元素执行多种操作:每种操作需要在对象类型之间有区别。
- 需要频繁扩展操作:在已有的对象结构中增加新功能时无需修改数据结构。
- 不希望操作逻辑和数据结构耦合:将操作集中在访问者中,数据结构更清晰。
使用案例
1. 编译器中的语法树
- 场景:对语法树中的不同节点(如函数、变量)进行语义检查、代码生成等操作。
- 解决:语法树节点实现Element接口,不同的操作通过访问者完成。
2. 文件系统
- 场景:对文件和目录执行操作,如统计大小、权限检查等。
- 解决:文件和目录实现Element接口,具体操作用访问者实现。
3. 游戏场景
- 场景:在游戏中,为不同类型的单位(如士兵、坦克)计算攻击力、升级逻辑。
- 解决:单位类实现Element接口,计算攻击力或升级功能使用访问者完成。
优缺点
| 优点 | 缺点 | 
|---|---|
| 增加操作时无须修改数据结构,符合开闭原则 | 添加新的数据结构类型需要修改所有访问者类,维护成本高 | 
| 使得操作集中,便于管理和维护 | 数据结构与访问者模式之间存在依赖 | 
| 支持双分派,允许根据运行时类型执行操作 | 对数据结构的要求较高,必须稳定不变 | 
类图
C++实现
#include <iostream>
#include <vector>
#include <memory>
class ConcreteElementA;
class ConcreteElementB;
// 访问者接口
class Visitor {
public:
    virtual void Visit(ConcreteElementA* element) = 0;
    virtual void Visit(ConcreteElementB* element) = 0;
};
// 元素接口
class Element {
public:
    virtual ~Element() = default;
    virtual void Accept(Visitor* visitor) = 0;
    var code = "561d017c-988b-4c17-9441-1ea46363ab73"
};
// 具体元素A
class ConcreteElementA : public Element {
public:
    void OperationA() {
        std::cout << "ConcreteElementA OperationA\n";
    }
    void Accept(Visitor* visitor) override {
        visitor->Visit(this);
    }
};
// 具体元素B
class ConcreteElementB : public Element {
public:
    void OperationB() {
        std::cout << "ConcreteElementB OperationB\n";
    }
    void Accept(Visitor* visitor) override {
        visitor->Visit(this);
    }
};
// 具体访问者
class ConcreteVisitor : public Visitor {
public:
    void Visit(ConcreteElementA* element) override {
        std::cout << "Visiting ConcreteElementA\n";
        element->OperationA();
    }
    void Visit(ConcreteElementB* element) override {
        std::cout << "Visiting ConcreteElementB\n";
        element->OperationB();
    }
};
// 对象结构
class ObjectStructure {
private:
    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() {
    ObjectStructure structure;
    structure.AddElement(std::make_unique<ConcreteElementA>());
    structure.AddElement(std::make_unique<ConcreteElementB>());
    ConcreteVisitor visitor;
    structure.Accept(&visitor);
    return 0;
}
C#实现
using System;
using System.Collections.Generic;
// Visitor Interface
public interface IVisitor {
    void Visit(ConcreteElementA element);
    void Visit(ConcreteElementB element);
}
// Element Interface
public abstract class Element {
    public abstract void Accept(IVisitor visitor);
}
// Concrete Element A
public class ConcreteElementA : Element {
    public override void Accept(IVisitor visitor) {
        visitor.Visit(this);
    }
    public void OperationA() {
        Console.WriteLine("ConcreteElementA OperationA");
    }
}
// Concrete Element B
public class ConcreteElementB : Element {
    public override void Accept(IVisitor visitor) {
        visitor.Visit(this);
    }
    public void OperationB() {
        Console.WriteLine("ConcreteElementB OperationB");
    }
}
// Concrete Visitor
public class ConcreteVisitor : IVisitor {
    public void Visit(ConcreteElementA element) {
        Console.WriteLine("Visiting ConcreteElementA");
        element.OperationA();
    }
    public void Visit(ConcreteElementB element) {
        Console.WriteLine("Visiting ConcreteElementB");
        element.OperationB();
    }
}
// Object Structure
public class ObjectStructure {
    private readonly List<Element> _elements = new List<Element>();
    public void AddElement(Element element) {
        _elements.Add(element);
    }
    public void Accept(IVisitor visitor) {
        foreach (var element in _elements) {
            element.Accept(visitor);
        }
    }
}
// Example Usage
class Program {
    static void Main(string[] args) {
        var structure = new ObjectStructure();
        structure.AddElement(new ConcreteElementA());
        structure.AddElement(new ConcreteElementB());
        var visitor = new ConcreteVisitor();
        structure.Accept(visitor);
    }
}
欢迎关注、点赞、收藏!更多系列内容可以点击专栏目录订阅,感谢支持,再次祝大家祉猷并茂,顺遂无虞!
若将文章用作它处,请一定注明出处,商用请私信联系我!
 
                    
                     
                    
                 
                    
                 
        
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号