Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Для чого використовується патерн Visitor?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Патерн **Visitor (Відвідувач)** використовується, коли потрібно **виконувати різні операції над об'єктами складної структури**, але **не змінюючи класи цих об'єктів**. **Ключове:** Visitor - це "гість", який приходить в об'єкти, робить з ними потрібну дію, але не змінює їх зсередини.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)ЗображенняПатерн **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 - це "гість", який **приходить в об'єкти**, > робить з ними потрібну дію, > але **не змінює їх зсередини**.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.