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

Что это такое

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

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


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

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

Новые операции, неизменные классы

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

Prompt
Напишите PHP-скрипт с паттерном Visitor: фигуры Circle и Rectangle с методом accept, интерфейс Visitor с visitCircle и visitRectangle, посетитель AreaPrinter, печатающий площадь каждой фигуры, и посетитель NamePrinter, печатающий имя каждой фигуры. Пройдите список фигур обоими посетителями.
Вывод: PHP-скрипт

Когда его применять

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

Откажитесь, когда семейство классов ещё растёт: каждый новый класс заставляет менять каждого посетителя. Часто проверка instanceof или match по $shape::class делает ту же работу с меньшим количеством механики — берите посетителя, когда размножаются операции, а не классы.


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

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

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