Які класи беруть участь у Visitor?
У реалізації патерна Visitor (Відвідувач) беруть участь п'ять основних ролей (класів), які розділяють структуру об'єктів і операції, що виконуються над ними.
1. Element (Елемент)
Інтерфейс або абстрактний клас, який приймає відвідувача. Кожен елемент структури повинен уміти "пускати" відвідувача всередину, щоб той міг виконати потрібну дію.
Основний метод:
void accept(Visitor visitor);Завдання:
- оголосити метод
accept(), що приймає об'єктVisitor; - делегувати йому обробку, викликаючи
visitor.visit(this).
Приклад:
interface Shape {
void accept(ShapeVisitor visitor);
}2. ConcreteElement (Конкретний елемент)
Реальні класи, що складають структуру даних (вузли, файли, фігури тощо).
Кожен реалізує метод accept() і викликає відповідний метод visit() відвідувача,
передаючи себе як аргумент.
Завдання:
- визначити, як "запрошувати" відвідувача;
- зберігати дані, над якими відвідувач буде працювати.
Приклад:
class Circle implements Shape {
public void accept(ShapeVisitor visitor) {
visitor.visit(this); // подвійна диспетчеризація
}
}
class Square implements Shape {
public void accept(ShapeVisitor visitor) {
visitor.visit(this);
}
}3. Visitor (Відвідувач)
Інтерфейс, який визначає набір методів visit()
для кожного типу елемента, який може бути відвіданий.
Завдання:
- оголосити окремі методи для обробки кожного конкретного типу елемента;
- забезпечувати "зовнішні" операції над об'єктами, не змінюючи їхні класи.
Приклад:
interface ShapeVisitor {
void visit(Circle circle);
void visit(Square square);
}4. ConcreteVisitor (Конкретний відвідувач)
Реалізація інтерфейсу Visitor, у якій описана конкретна операція,
що виконується над кожним типом елемента.
Завдання:
- реалізувати всі методи
visit(); - визначати конкретну поведінку (експорт, підрахунок, валідація тощо).
Приклад:
class AreaVisitor implements ShapeVisitor {
public void visit(Circle circle) {
System.out.println("Обчислення площі кола");
}
public void visit(Square square) {
System.out.println("Обчислення площі квадрата");
}
}5. ObjectStructure (Структура об'єктів)
Компонент, який зберігає і керує колекцією елементів.
Він може надавати ітерацію і викликати accept() для кожного елемента,
щоб відвідувач обробив усю структуру.
Завдання:
- агрегувати елементи;
- забезпечувати обхід усієї структури.
Приклад:
class Drawing {
private List<Shape> shapes = new ArrayList<>();
public void addShape(Shape shape) { shapes.add(shape); }
public void apply(ShapeVisitor visitor) {
for (Shape shape : shapes) {
shape.accept(visitor);
}
}
}6. Підсумкова структура взаємодій
+-------------------+
| Visitor |
|-------------------|
| + visit(Circle) |
| + visit(Square) |
+---------^---------+
|
+-----------+-----------+
| ConcreteVisitor |
| (наприклад: AreaVisitor) |
+------------------------+
(викликає)
↑
+--------------------------------+
| Element |
|--------------------------------|
| + accept(Visitor visitor) |
+-----------------^---------------+
|
+-----------+-----------+
| ConcreteElement |
| (Circle, Square, etc.)|
+-----------------------+
↑
+------------------+
| ObjectStructure |
|------------------|
| + apply(visitor) |
+------------------+Висновок
| Клас | Роль |
|---|---|
| Element | Визначає інтерфейс для "приймання" відвідувача |
| ConcreteElement | Реалізує accept() і викликає visit(this) |
| Visitor | Визначає інтерфейс для всіх операцій над елементами |
| ConcreteVisitor | Реалізує конкретні дії для кожного типу |
| ObjectStructure | Керує колекцією елементів і дозволяє відвідувачу обійти їх |
Підсумок:
У Visitor логіка дій виноситься в окремі класи (відвідувачі), а елементи структури лише надають "точку входу" -
accept(). Це дозволяє додавати нові операції без зміни елементів.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.