Паттерны / Паттерны поведения
image

#include <vector>
#include <iostream>
using namespace std;

class Engine;
class Wheel;
class Car;

//Visitor
class CarVisitor {
public:
    virtual void visit(Engine* engine) = 0;
    virtual void visit(Wheel* wheel) = 0;
    virtual void visit(Car* car) = 0;
};

class Element {
public:
    virtual void accept(CarVisitor* v) = 0;
};

//ConcreteElement
class Enginepublic Element {
public:
    void accept(CarVisitor* v) {
        v->visit(this);
    }
};

//ConcreteElement
class Wheelpublic Element {
private:
    int number;

public:
    Wheel(int number) {
        this->number = number;
    }

    int getNumber() {
        return number;
    }

    void accept(CarVisitor* v) {
        v->visit(this);
    }
};

//ConcreteElement
class Carpublic Element {
private:
    vector<Element*> items = {
        new Engine(),
        new Wheel(1), new Wheel(2),
        new Wheel(3), new Wheel(4)};

public:
    void accept(CarVisitor* v) {
        for (Element* e : items) {
            e->accept(v);
        }
        v->visit(this);
    }
};

//ConcreteVisitor
class TestCarVisitorpublic CarVisitor {
    public:
    void visit(Engine* engine) {
        cout << "test engine\n";
    }

    void visit(Wheel* wheel) {
        cout << "test wheel #" <<
        wheel->getNumber() << "\n";
    }

    void visit(Car* car) {
        cout << "test car\n";
    }
};

//ConcreteVisitor
class RepairCarVisitorpublic CarVisitor {
public:
    void visit(Engine* engine) {
        cout << "repair engine\n";
    }

    void visit(Wheel* wheel) {
        cout << "repair wheel #" <<
        wheel->getNumber() << "\n";
    }

    void visit(Car* car) {
        cout << "repair car\n";
    }
};

//Client
Car car;
CarVisitor* v1 = new TestCarVisitor();
CarVisitor* v2 = new RepairCarVisitor();

car.accept(v1);
car.accept(v2);


Представляет операцию, которую надо выполнить над элементами объекта. Позволяет определить новую операцию, не меняя классы элементов, к которым он применяется.