Возможные реализации для решения конкретных задач

Visitor

Посетитель с приведением типа между базовыми классами

Реализация посетителя с приведением типа между базовыми классами использует пустой абстрактный класс посетителя, который дополняется посетителями конкретных типов при помощи реализации идиомы MixIn.

Подход может быть использован, в случае, если требуется создавать посетители с сильно разнящимся поведением относительно посещаемых типов, когда мы не хотим размещать разную логику обработки сущностей рядом в одном классе.

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

using namespace std;
int main() 
{
    shared_ptr<Shape> figure = make_shared<Figure>(
        initializer_list<shared_ptr<Shape>>(
            { make_shared<Circle>(1), make_shared<Square>(2) }
        )
    );
    figure->accept(Draw{});
}

Посетитель с использованием шаблона variant ("безопасный" union)

#include <iostream>
#include <vector>
#include <variant>

using namespace std;
int main()
{
    using Shapes = vector<Shape>;
    Shapes fiqure = Formation::initialization({ Circle{}, Square{} });
    for (const auto& elem : fiqure)
        std::visit(Draw{}, elem);
}

Шаблонный посетитель (Template visitor) с использованием паттерна CRTP (Curiously Recurring Template Pattern)

Реализация шаблонного посетителя прибегает к вариативным шаблонам классов для определения типа посетителя, который посещает заданные классы. За счёт использования CRTP можно избавиться от реализации метода accept в каждой сущности, перенеся ответственность за это на класс Visitable.

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

using namespace std;
int main()
{
    Point p;
    shared_ptr<Composite> figure = make_shared<Composite>(
        initializer_list<shared_ptr<Shape>>(
            { make_shared<Figure>(p), make_shared<Camera>(p), make_shared<Figure>(p) }
        )
    );
    shared_ptr<ShapeVisitor> visitor = make_shared<DrawVisitor>();
    figure->accept(visitor);
}

Last updated

Was this helpful?