首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >访问者模式

访问者模式

作者头像
码事漫谈
发布2024-12-20 12:58:33
发布2024-12-20 12:58:33
24100
代码可运行
举报
文章被收录于专栏:设计模式设计模式
运行总次数:0
代码可运行

访问者模式详解

概念

访问者模式(Visitor Pattern)是一种行为型设计模式,用于将数据结构与其操作解耦。通过在不改变数据结构的前提下,增加新的操作,访问者模式提供了一种灵活的方式来实现功能扩展。

关键特性
  • 分离操作:将具体操作从对象本身分离,使得操作逻辑集中在访问者中。
  • 支持扩展:容易增加新的操作,但增加新的数据结构时会比较复杂。
  • 双分派机制:通过在访问者和元素之间的双向调用实现。

适用场景

  • 需要对对象结构中的元素执行多种操作:每种操作需要在对象类型之间有区别。
  • 需要频繁扩展操作:在已有的对象结构中增加新功能时无需修改数据结构。
  • 不希望操作逻辑和数据结构耦合:将操作集中在访问者中,数据结构更清晰。

使用案例

1. 编译器中的语法树
  • 场景:对语法树中的不同节点(如函数、变量)进行语义检查、代码生成等操作。
  • 解决:语法树节点实现Element接口,不同的操作通过访问者完成。
2. 文件系统
  • 场景:对文件和目录执行操作,如统计大小、权限检查等。
  • 解决:文件和目录实现Element接口,具体操作用访问者实现。
3. 游戏场景
  • 场景:在游戏中,为不同类型的单位(如士兵、坦克)计算攻击力、升级逻辑。
  • 解决:单位类实现Element接口,计算攻击力或升级功能使用访问者完成。

优缺点

优点

缺点

增加操作时无须修改数据结构,符合开闭原则

添加新的数据结构类型需要修改所有访问者类,维护成本高

使得操作集中,便于管理和维护

数据结构与访问者模式之间存在依赖

支持双分派,允许根据运行时类型执行操作

对数据结构的要求较高,必须稳定不变

类图


C++实现

代码语言:javascript
代码运行次数:0
运行
复制
#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;
};

// 具体元素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#实现

代码语言:javascript
代码运行次数:0
运行
复制
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);
    }
}

欢迎关注、点赞、收藏!更多系列内容可以点击专栏目录订阅,感谢支持,再次祝大家祉猷并茂,顺遂无虞

若将文章用作它处,请一定注明出处,商用请私信联系我!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 访问者模式详解
    • 概念
    • 适用场景
    • 使用案例
      • 1. 编译器中的语法树
      • 2. 文件系统
      • 3. 游戏场景
    • 优缺点
    • 类图
    • C++实现
    • C#实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档