Visitor (Посетитель): добавление операций к сложным структурам без изменения их классов
Visitor позволяет добавлять новые операции к объектам сложной структуры, не изменяя их классы. Вместо внедрения логики внутрь элементов дерева операции выносятся в отдельные «посетители», которые обходят структуру.
Паттерн особенно полезен в AST, XML/JSON-деревьях, DOM-моделях, BPM-процессах, финансовых моделях, компиляторах, интеграционных схемах и системах отчетности.
Visitor делает архитектуру гибкой: новые действия добавляются как отдельные классы посетителей, избегая модификации самой структуры и соблюдая принцип открытости/закрытости.
Visitor — один из самых архитектурных паттернов, потому что в реальных информационных системах почти всегда существуют сложные структурированные данные: деревья документов, каталоги, иерархии процессов, JSON/XML модели, графы сущностей, AST выражений, структуры UI, модели расчётов. Проблема в том, что разработчикам часто нужно выполнять разные операции над этими структурами:
-
проверка правильности,
-
генерация отчетов,
-
сериализация,
-
валидация,
-
экспорт/импорт,
-
визуализация,
-
расчёты,
-
анализ.
Если эти операции встроить в сами структуры, классы быстро «распухнут», нарушится SRP, а добавление новых функций станет кошмаром.
Visitor решает проблему:
структуру не трогаем — логика помещается в посетителей.
Как работает Visitor
1. У нас есть сложная структура: дерево или граф
Например:
-
элементы документа,
-
элементы оргструктуры,
-
AST выражений,
-
DOM-узлы,
-
диаграммы,
-
BPM шаги.
Каждый элемент реализует метод accept(visitor).
2. Посетитель реализует отдельные методы для каждого типа элементов
scssvisitParagraph(...) visitSection(...) visitImage(...)
3. Структура вызывает посетителя
Каждый узел вызывает свой «visit»-метод, передавая ссылку на себя.
Так формируется «двойная диспетчеризация», позволяющая выполнять разные действия над разными типами узлов, не засоряя сами классы структуры.
Где используется Visitor в архитектуре
1. AST (деревья разбора) — компиляторы, SQL-парсеры, DSL
Все компиляторы (Java, C#, Python, Kotlin) используют Visitor для:
-
обхода синтаксического дерева,
-
проверки типов,
-
оптимизации,
-
генерации байткода,
-
трансформаций.
2. XML/JSON DOM
DOM API — классическое применение Visitor:
-
валидация документа,
-
экспорт,
-
преобразования,
-
сигнатуры,
-
схемы.
3. BPMN, EPC, DFD
Workflow-платформы:
-
Camunda
-
jBPM
-
Activiti
-
Bonita BPM
используют посетителей для обработки моделей процессов.
4. Интеграционные схемы и ETL
Visitor нужен для:
-
анализа потоков данных,
-
построения плана выполнения,
-
оптимизации SQL-операторов,
-
генерации ETL-пайплайна.
5. Финансовые модели
Финансовые инструменты (деривативы, опционы, ставки) формируют сложные объекты.
Visitor позволяет:
-
рассчитать стоимость,
-
провести аудит,
-
выполнить риск-анализ,
-
провести валидацию.
Каждый расчет — отдельный посетитель.
6. UI-деревья и виджеты
Фреймворки используют Visitor для:
-
рендеринга,
-
применения стилей,
-
трансформации,
-
измерения размеров,
-
построения дерева компоновки.
7. Graph-модели
Visitor позволяет обходить:
-
социальные графы,
-
графы зависимостей,
-
дороги,
-
трассировки.
Преимущества Visitor
-
позволяет добавлять новые операции без изменения структуры;
-
сохраняет чистоту моделей;
-
идеально работает с Composite;
-
позволяет разделять ответственность;
-
повышает тестируемость;
-
облегчает расширение функциональности.
Недостатки
-
трудно применять, если структура часто меняется;
-
требует много методов
visit*; -
сложен для новичков;
-
нарушает инкапсуляцию, если нужно читать внутреннее состояние объектов.
Но в зрелых архитектурах Visitor незаменим.
Visitor в российских учебниках
Как правило — в главах:
-
деревья иерархий,
-
обработка моделей,
-
проектирование компиляторов,
-
анализ структурированных данных,
-
моделирование процессов.
Почему архитектор обязан знать Visitor
Потому что в любой крупной системе есть структуры, которые:
-
сложны,
-
иерархичны,
-
долго живут,
-
часто обрабатываются разными способами,
-
не должны засоряться логикой.
Visitor позволяет добавлять функциональность десятилетиями, не ломая модель.
Это один из самых мощных инструментов для ИС, интеграций, компиляторов, BPM, ETL и аналитических систем.