【设计模式之访问者模式 -- C++】

访问者模式 -- 操作对象,分离算法

访问者模式(Visitor Pattern)是一种将算法与对象结构分离的设计模式。这种模式主要用于操作一个由许多对象构成的复杂对象结构,它能够在不修改这些对象的类的前提下定义作用于这些对象的新操作。

组成
  1. 访问者(Visitor)接口:定义了对每一个元素(Element)类访问操作的接口。通常会有一个访问方法对应每种类型的元素。
  2. 具体访问者(Concrete Visitor)类:实现访问者接口,定义了对每一个元素的具体访问行为。
  3. 元素(Element)接口:定义了一个接受访问者的方法(accept),该方法通常有一个访问者作为参数。
  4. 具体元素(Concrete Element)类:实现元素接口,定义了接受访问者的具体操作,通常是让访问者访问自己的元素。
  5. 对象结构(Object Structure):一个元素的集合,它提供了一个接口,允许访问者遍历自己的元素。
工作原理
  1. 访问者模式通过将数据结构与数据操作分离,使得在不修改已有程序结构的情况下,可以向已有的对象结构中添加新的操作。
  2. 当需要对一个复杂的对象结构(如组合树)进行操作时,可以使用访问者模式来避免对每个节点类都添加操作。相反,可以创建访问者类来专门处理这些操作。
  3. 元素类通过接受一个访问者对象,将自身作为参数传递给访问者的访问方法,从而实现对元素的操作。
优点
  1. 易于添加新的操作,增强了系统的灵活性。
  2. 将相关的操作集中到一个访问者对象中,而不是分散在多个元素类中,有助于集中管理和维护。
缺点
  1. 增加新的元素类变得困难,因为每增加一个新的元素类,都需要在每个访问者类中增加相应的访问操作。
  2. 可能会破坏封装,因为访问者模式通常需要元素类暴露一些访问其内部状态的操作,这可能会违反其封装原则。
实现
  1. 访问者(Visitor)接口:定义了对每一个元素(Element)类访问操作的接口。通常会有一个访问方法对应每种类型的元素。
cpp 复制代码
class Visitor {
public:
    virtual void visitConcreteElementA(ConcreteElementA* elementA) = 0;
    virtual void visitConcreteElementB(ConcreteElementB* elementB) = 0;
    virtual ~Visitor() = default;
};
  1. 具体访问者(Concrete Visitor)类:实现访问者接口,定义了对每一个元素的具体访问行为。
cpp 复制代码
// 具体访问者1
class ConcreteVisitor1 : public Visitor {
public:
    void visitConcreteElementA(ConcreteElementA* elementA) override {
        std::cout << "ConcreteVisitor1 visiting ConcreteElementA" << std::endl;
        elementA->operationA();
    }
    void visitConcreteElementB(ConcreteElementB* elementB) override {
        std::cout << "ConcreteVisitor1 visiting ConcreteElementB" << std::endl;
        elementB->operationB();
    }
};

// 具体访问者2
class ConcreteVisitor2 : public Visitor {
public:
    void visitConcreteElementA(ConcreteElementA* elementA) override {
        std::cout << "ConcreteVisitor2 visiting ConcreteElementA" << std::endl;
        elementA->operationA();
    }
    void visitConcreteElementB(ConcreteElementB* elementB) override {
        std::cout << "ConcreteVisitor2 visiting ConcreteElementB" << std::endl;
        elementB->operationB();
    }
};
  1. 元素(Element)接口:定义了一个接受访问者的方法(accept),该方法通常有一个访问者作为参数。
cpp 复制代码
class Element {
public:
    virtual void accept(Visitor* visitor) = 0; // 接受访问者
    virtual ~Element() = default;
};
  1. 具体元素(Concrete Element)类:实现元素接口,定义了接受访问者的具体操作,通常是让访问者访问自己的元素。
cpp 复制代码
// 具体元素A
class ConcreteElementA : public Element {
public:
    void accept(Visitor* visitor) override {
        visitor->visitConcreteElementA(this);
    }
    void operationA() {
        std::cout << "ConcreteElementA operationA" << std::endl;
    }
};

// 具体元素B
class ConcreteElementB : public Element {
public:
    void accept(Visitor* visitor) override {
        visitor->visitConcreteElementB(this);
    }
    void operationB() {
        std::cout << "ConcreteElementB operationB" << std::endl;
    }
};
  1. 对象结构(Object Structure):一个元素的集合,它提供了一个接口,允许访问者遍历自己的元素。
cpp 复制代码
int main() {
    std::vector<std::unique_ptr<Element>> elements;
    elements.push_back(std::make_unique<ConcreteElementA>());
    elements.push_back(std::make_unique<ConcreteElementB>());

    ConcreteVisitor1 visitor1;
    ConcreteVisitor2 visitor2;

    for (auto& element : elements) {
        element->accept(&visitor1);
        element->accept(&visitor2);
    }

    return 0;
}
  1. 结果
shell 复制代码
ConcreteVisitor1 visiting ConcreteElementA
ConcreteElementA operationA
ConcreteVisitor2 visiting ConcreteElementA
ConcreteElementA operationA
ConcreteVisitor1 visiting ConcreteElementB
ConcreteElementB operationB
ConcreteVisitor2 visiting ConcreteElementB
ConcreteElementB operationB
相关推荐
JCBP_18 分钟前
QT(4)
开发语言·汇编·c++·qt·算法
会开花的二叉树1 小时前
继承与组合:C++面向对象的核心
java·开发语言·c++
潮汐退涨月冷风霜2 小时前
数字图像处理(1)OpenCV C++ & Opencv Python显示图像和视频
c++·python·opencv
第七序章3 小时前
【C++STL】list的详细用法和底层实现
c语言·c++·自然语言处理·list
逆小舟5 小时前
【Linux】人事档案——用户及组管理
linux·c++
Magnetic_h9 小时前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa
风中的微尘9 小时前
39.网络流入门
开发语言·网络·c++·算法
A阳俊yi9 小时前
设计模式——结构型模式
设计模式
混分巨兽龙某某10 小时前
基于Qt Creator的Serial Port串口调试助手项目(代码开源)
c++·qt creator·串口助手·serial port
小冯记录编程10 小时前
C++指针陷阱:高效背后的致命危险
开发语言·c++·visual studio