Skip to main content

Для чого використовується патерн Visitor?

Патерн Visitor (Відвідувач) використовується, коли потрібно виконувати різні операції над об'єктами складної структури, але не змінюючи класи цих об'єктів.

Він дозволяє винести поведінку (операції) за межі ієрархії класів, і додавати нові дії без зміни самих елементів структури.


1. Основна ідея

Розділити структуру даних і поведінку, що застосовується до неї.

Структура залишається незмінною, а нові операції додаються через "відвідувачів", які обходять елементи і виконують над ними потрібну дію.


2. Учасники патерна

РольОпис
Visitor (Відвідувач)Інтерфейс, що визначає набір операцій для різних типів елементів
ConcreteVisitorКонкретні реалізації дій (наприклад, експорт, підрахунок, перевірка)
Element (Елемент)Інтерфейс, який приймає відвідувача (accept(Visitor v))
ConcreteElementРеальні елементи структури, які "приймають" відвідувача
ObjectStructureКолекція елементів, яку відвідувач може обійти

3. Приклад (Java)

Уявімо, у нас є структура документів різних типів, і ми хочемо виконувати над ними різні операції (наприклад, підрахунок символів, експорт у PDF тощо), але не хочемо змінювати їхній код щоразу.

Інтерфейси

java
interface DocumentVisitor { void visit(TextDocument doc); void visit(ImageDocument doc); } interface DocumentElement { void accept(DocumentVisitor visitor); }

Елементи

java
class TextDocument implements DocumentElement { String text = "Hello Visitor!"; public void accept(DocumentVisitor visitor) { visitor.visit(this); } } class ImageDocument implements DocumentElement { String name = "image.png"; public void accept(DocumentVisitor visitor) { visitor.visit(this); } }

Конкретні відвідувачі

java
class WordCountVisitor implements DocumentVisitor { public void visit(TextDocument doc) { System.out.println("Слів: " + doc.text.split(" ").length); } public void visit(ImageDocument doc) { System.out.println("Для зображення підрахунок слів не застосовний"); } } class ExportVisitor implements DocumentVisitor { public void visit(TextDocument doc) { System.out.println("Експорт тексту в PDF: " + doc.text); } public void visit(ImageDocument doc) { System.out.println("Експорт зображення в PDF: " + doc.name); } }

Використання

java
List<DocumentElement> docs = List.of(new TextDocument(), new ImageDocument()); DocumentVisitor visitor = new ExportVisitor(); for (DocumentElement d : docs) { d.accept(visitor); }

4. Що це дає

  • Елементи (структура даних) не змінюються, а відвідувачі реалізують різні сценарії обробки.
  • Можна легко додавати нові дії, просто створивши новий Visitor.
  • Підтримується подвійна диспетчеризація: поведінка залежить і від типу відвідувача, і від типу елемента.

5. Переваги

Додавання нових операцій без зміни класів елементів. Централізація логіки обробки кожного типу. Розділення даних і дій - код стає чистішим.


6. Недоліки

  • Додавання нових типів елементів вимагає зміни всіх відвідувачів.
  • Збільшується кількість класів.
  • Використовує подвійну диспетчеризацію, що ускладнює архітектуру.

7. Коли використовувати

  • Коли потрібно часто додавати нові операції, але структура даних рідко змінюється.
  • Коли об'єкти різних класів повинні оброблятися єдиним способом.
  • Приклад: AST-парсери, компілятори, експорт даних, звітні системи.

Висновок

Патерн Visitor використовується, щоб:

  • розділити структуру і операції над нею,
  • додавати нові дії без зміни класів елементів,
  • забезпечити обхід і обробку різних типів об'єктів єдиною логікою.

Підсумок:

Visitor - це "гість", який приходить в об'єкти, робить з ними потрібну дію, але не змінює їх зсередини.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.