【设计模式之访问者模式 -- 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
相关推荐
别动我齐刘海3 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
程序员老陆3 小时前
C++ std::promise深度解析
c++·程序设计
青少儿编程课堂4 小时前
迪杰斯特拉(Dijkstra)算法:单源最短路与赛场路线规划
c++·python·算法·bfs·信息学竞赛
沫璃染墨6 小时前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss
道尔柯南7 小时前
C++ 面向对象编程入门:类和对象(上)
开发语言·c++·算法
aqiu1111118 小时前
【C++算法打怪专栏】C++ `unordered_set` 常用初始化与插入方法总结
开发语言·c++·算法
Terra.K8 小时前
高精度阶乘求和模板深度解析
开发语言·c++·算法
智码看视界9 小时前
C++智能指针全景剖析及面试20问
开发语言·c++·深度学习·面试·内存管理·智能指针
Peregrine99 小时前
C++ - > 类和对象
java·c++·算法
‎ദ്ദിᵔ.˛.ᵔ₎11 小时前
c++11:fuction包装器
开发语言·c++