Перейти к основному содержимому

Что это такое

Паттерн Посетитель (Visitor) добавляет новую операцию к семейству типов, не изменяя их. Типы один раз учатся одному — accept(visitor), — и с этого момента каждая новая операция — это просто новый посетитель с одним методом для каждого типа.

Он меняет привычный баланс: добавлять операции становится легко, а добавление типов становится дорогим изменением.


Пример: операции над фигурами

Фигуры больше не меняются. Вывод площадей — это один посетитель, вывод названий — другой, а посетитель для экспорта в SVG, добавленный завтра, не затронет ни Circle, ни Rectangle.

Новые операции, нетронутые типы

Оба посетителя обходят один и тот же список фигур через одну и ту же «дверь» accept. Каждый посетитель хранит всю операцию в одном месте, вместо того чтобы разбрасывать её по типам.

Prompt
Напишите программу на Python с паттерном Посетитель: фигуры Circle и Rectangle в виде dataclass с методом accept, протокол Visitor с методами visit_circle и visit_rectangle, посетитель AreaPrinter, выводящий площадь каждой фигуры, и посетитель NamePrinter, выводящий название каждой фигуры. Обойдите список фигур обоими посетителями.
Вывод: полная программа на Python

Когда его использовать

Используйте его, когда у стабильного семейства типов постоянно появляются новые операции — компиляторы, обходящие синтаксические деревья, документы, получающие новые экспортёры, фигуры, получающие средства отрисовки и измерения.

Не используйте его, когда семейство типов ещё растёт: каждый новый тип требует изменения в каждом посетителе. Во многих программах на Python оператор match по типам делает ту же работу с меньшим количеством кода — выбирайте посетителя, когда множатся операции, а не типы.


Плюсы и минусы

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

Минусы: двойная диспетчеризация (accept вызывает метод посетителя в ответ) сбивает с толку новичков; добавление одного посещаемого типа означает правку каждого посетителя; интерфейс посещаемого семейства фиксируется рано.