当前位置: 首页 > article >正文

23种设计模式-访问者(Visitor)设计模式

文章目录

  • 一.什么是访问者模式?
  • 二.访问者模式的结构
  • 三.访问者模式的应用场景
  • 四.访问者模式的优缺点
  • 五.访问者模式的C++实现
  • 六.访问者模式的JAVA实现
  • 七.代码解释
  • 八.总结

类图: 访问者设计模式类图

一.什么是访问者模式?

访问者模式(Visitor Pattern)是一种行为型设计模式,允许在不更改元素类的情况下,为对象结构中的元素增加新的操作。访问者模式通过将操作从元素类中抽离出来,实现操作的扩展。
 在访问者模式中,核心思想是将数据结构和操作分开,数据结构负责提供必要的接口,而具体的操作逻辑由访问者实现。

二.访问者模式的结构

  • Visitor(访问者接口):声明一组访问方法,每个方法对应一种具体的元素类型。
  • ConcreteVisitor(具体访问者):实现访问者接口中声明的操作,对不同的元素提供不同的处理。
  • Element(元素接口):定义一个Accept方法,用于接收访问者对象。
  • ConcreteElement(具体元素):实现元素接口,并在Accept方法中调用访问者的相应方法。
  • ObjectStructure(对象结构):提供元素的容器,负责存储和遍历元素。
    在这里插入图片描述

三.访问者模式的应用场景

  1. 数据结构稳定,操作逻辑需要频繁变化:例如编译器中的语法树遍历。
  2. 需要对一组不相关的类执行操作:如不同形状的图形对象(圆形、矩形等)。
  3. 需要集中管理行为,而不想污染元素类

四.访问者模式的优缺点

  • 优点
    • 增加新的操作很方便,只需新增一个具体访问者类。
    • 遵循单一职责原则,将操作与元素本身解耦。
  • 缺点
    • 增加新的元素类型需要修改所有访问者,违背了开闭原则。
    • 对象结构不容易扩展。

五.访问者模式的C++实现

#include <iostream>
#include <vector>
#include <memory>

// 前置声明,避免循环引用
class ConcreteElementA;
class ConcreteElementB;
class Visitor;

// 访问者接口(Visitor)
class Visitor {
public:
    virtual void visitConcreteElementA(ConcreteElementA& element) = 0;
    virtual void visitConcreteElementB(ConcreteElementB& element) = 0;
    virtual ~Visitor() = default;
};

// 元素接口(Element)
class Element {
public:
    virtual void accept(std::shared_ptr<Visitor> visitor) = 0;
    virtual ~Element() = default;
};

// 具体元素 A(ConcreteElementA)
class ConcreteElementA : public Element {
public:
    void accept(std::shared_ptr<Visitor> visitor) override {
        visitor->visitConcreteElementA(*this);
    }

    void operationA() {
        std::cout << "ConcreteElementA specific operation.\n";
    }
};

// 具体元素 B(ConcreteElementB)
class ConcreteElementB : public Element {
public:
    void accept(std::shared_ptr<Visitor> visitor) override {
        visitor->visitConcreteElementB(*this);
    }

    void operationB() {
        std::cout << "ConcreteElementB specific operation.\n";
    }
};

// 具体访问者 1(ConcreteVisitor1)
class ConcreteVisitor1 : public Visitor {
public:
    void visitConcreteElementA(ConcreteElementA& element) override {
        std::cout << "ConcreteVisitor1 visiting ConcreteElementA.\n";
        element.operationA();
    }

    void visitConcreteElementB(ConcreteElementB& element) override {
        std::cout << "ConcreteVisitor1 visiting ConcreteElementB.\n";
        element.operationB();
    }
};

// 具体访问者 2(ConcreteVisitor2)
class ConcreteVisitor2 : public Visitor {
public:
    void visitConcreteElementA(ConcreteElementA& element) override {
        std::cout << "ConcreteVisitor2 visiting ConcreteElementA.\n";
        element.operationA();
    }

    void visitConcreteElementB(ConcreteElementB& element) override {
        std::cout << "ConcreteVisitor2 visiting ConcreteElementB.\n";
        element.operationB();
    }
};

// 对象结构(ObjectStructure)
class ObjectStructure {
private:
    std::vector<std::shared_ptr<Element>> elements;

public:
    void addElement(std::shared_ptr<Element> element) {
        elements.push_back(element);
    }

    void accept(std::shared_ptr<Visitor> visitor) {
        for (auto& element : elements) {
            element->accept(visitor);
        }
    }
};

// 测试代码
int main() {
    // 创建对象结构
    ObjectStructure objectStructure;

    // 添加元素
    objectStructure.addElement(std::make_shared<ConcreteElementA>());
    objectStructure.addElement(std::make_shared<ConcreteElementB>());

    // 创建访问者 1 并访问
    std::shared_ptr<Visitor> visitor1 = std::make_shared<ConcreteVisitor1>();
    std::cout << "Using ConcreteVisitor1:\n";
    objectStructure.accept(visitor1);

    // 创建访问者 2 并访问
    std::shared_ptr<Visitor> visitor2 = std::make_shared<ConcreteVisitor2>();
    std::cout << "\nUsing ConcreteVisitor2:\n";
    objectStructure.accept(visitor2);

    return 0;
}

六.访问者模式的JAVA实现

// 抽象访问者
interface Visitor {
    void VisitConcreteElementA(ConcreteElementA elementA);
    void VisitConcreteElementB(ConcreteElementB elementB);
}

// 具体访问者1
class ConcreteVisitor1 implements Visitor {
    @Override
    public void VisitConcreteElementA(ConcreteElementA elementA) {
        System.out.println("ConcreteVisitor1 visiting ConcreteElementA");
    }

    @Override
    public void VisitConcreteElementB(ConcreteElementB elementB) {
        System.out.println("ConcreteVisitor1 visiting ConcreteElementB");
    }
}

// 具体访问者2
class ConcreteVisitor2 implements Visitor {
    @Override
    public void VisitConcreteElementA(ConcreteElementA elementA) {
        System.out.println("ConcreteVisitor2 visiting ConcreteElementA");
    }

    @Override
    public void VisitConcreteElementB(ConcreteElementB elementB) {
        System.out.println("ConcreteVisitor2 visiting ConcreteElementB");
    }
}

// 抽象元素
abstract class Element {
    public abstract void Accept(Visitor visitor);
}

// 具体元素A
class ConcreteElementA extends Element {
    @Override
    public void Accept(Visitor visitor) {
        visitor.VisitConcreteElementA(this);
    }

    public void OperationA() {
        System.out.println("ConcreteElementA specific operation.");
    }
}

// 具体元素B
class ConcreteElementB extends Element {
    @Override
    public void Accept(Visitor visitor) {
        visitor.VisitConcreteElementB(this);
    }

    public void OperationB() {
        System.out.println("ConcreteElementB specific operation.");
    }
}

// 对象结构
class ObjectStructure {
    private final List<Element> elements = new ArrayList<>();

    public void Add(Element element) {
        elements.add(element);
    }

    public void Accept(Visitor visitor) {
        for (Element element : elements) {
            element.Accept(visitor);
        }
    }
}

// 客户端代码
public class VisitorPatternDemo {
    public static void main(String[] args) {
        // 创建对象结构
        ObjectStructure structure = new ObjectStructure();

        // 添加具体元素
        structure.Add(new ConcreteElementA());
        structure.Add(new ConcreteElementB());

        // 创建并使用访问者1
        ConcreteVisitor1 visitor1 = new ConcreteVisitor1();
        structure.Accept(visitor1);

        // 创建并使用访问者2
        ConcreteVisitor2 visitor2 = new ConcreteVisitor2();
        structure.Accept(visitor2);
    }
}

七.代码解释

  1. Element 接口和 ConcreteElement
    • Element接口定义了一个accept方法,具体元素类需要实现该方法,并在其中调用访问者的相应方法。
  2. Visitor 接口和 ConcreteVisitor
    • Visitor接口声明了针对每种具体元素的访问方法。
    • ConcreteVisitor1和ConcreteVisitor2实现了Visitor接口,并定义了对ConcreteElementA和ConcreteElementB的具体操作。
  3. ObjectStructure 类
    • ObjectStructure维护了一个元素集合,并提供accept方法,用于将访问者传递给集合中的每个元素。
  4. 测试代码
    • 创建了一个对象结构,并添加了两种具体元素。
    • 使用两个不同的访问者访问元素集合,展示了访问者模式的扩展性。

八.总结

访问者模式是一种将操作和数据结构分离的强大工具。当需要频繁添加新的操作或行为时,它提供了扩展性良好的解决方案。通过访问者模式,可以大幅简化复杂操作的管理,提升代码的可读性和维护性


http://www.kler.cn/a/400986.html

相关文章:

  • 使用Faiss构建音频特征索引并计算余弦相似度
  • 5G的SUCI、SUPI、5G-GUTI使用场景及关系
  • 如何在 Ubuntu 上安装 Jupyter Notebook
  • MySQL45讲 第二十四讲 MySQL是怎么保证主备一致的?——阅读总结
  • C指针之舞——指针探秘之旅
  • Tailscale 自建 Derp 中转服务器
  • MySQL 日志 主从复制
  • 多仓库分支同步策略:方法与工具全解析
  • C++ stack 容器
  • Javaweb梳理16——HTMLCSS使用
  • 2. langgraph中的react agent使用 (在react agent添加历史消息)
  • 『大模型笔记』AI自动化编程工具汇总!
  • Datawhale组队学习】模型减肥秘籍:模型压缩技术3——模型量化
  • 【D04】网络安全基本命令
  • Spark RDD中常用聚合算子源码层面的对比分析
  • [笔记]DCDC电路的基本拓扑结构
  • unity3d————碰撞和触发器发生的条件补充知识点
  • ue5入门教程:EventGraph
  • 视频智能分析软件LiteAIServer视频智能分析平台玩手机打电话检测算法
  • 卷积神经网络 (CNN)
  • java设计模式之 - 适配器模式
  • AVL树(c++版)
  • 农业银行手机银行系统介绍
  • 苍穹外卖 软件开发流程
  • Elasticsearch实战应用-dsl语句
  • fpga spi回环