Visitor (Посетитель)
Шаблон проектирования "Посетитель" (Visitor) позволяет добавлять новые операции к объектам, не изменяя их классы. Этот паттерн особенно полезен, когда у вас есть структура объектов с различными классами, и вы хотите выполнить операции над этими объектами, не изменяя их внутреннюю реализацию.
Основные компоненты паттерна "Посетитель":
- Посетитель (Visitor): интерфейс, который определяет методы для каждого типа элемента, который может быть посещен.
- Конкретный посетитель (Concrete Visitor): класс, который реализует интерфейс посетителя и определяет конкретные операции для каждого типа элемента.
- Элемент (Element): интерфейс, который определяет метод
accept
, который принимает посетителя. - Конкретные элементы (Concrete Elements): классы, реализующие интерфейс элемента и определяющие, как посетитель будет взаимодействовать с ними.
- Структура объектов (Object Structure): класс, который содержит коллекцию элементов и позволяет посетителю проходить по ним.
Пример на Java
Рассмотрим пример, в котором у нас есть структура объектов, представляющая различные фигуры (круги и прямоугольники), и мы хотим вычислить их площади.
// Интерфейс посетителя
interface ShapeVisitor {
void visit(Circle circle);
void visit(Rectangle rectangle);
}
// Интерфейс элемента
interface Shape {
void accept(ShapeVisitor visitor);
}
// Конкретный элемент: Круг
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
@Override
public void accept(ShapeVisitor visitor) {
visitor.visit(this);
}
}
// Конкретный элемент: Прямоугольник
class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
@Override
public void accept(ShapeVisitor visitor) {
visitor.visit(this);
}
}
// Конкретный посетитель: Вычисление площади
class AreaCalculator implements ShapeVisitor {
private double totalArea = 0;
@Override
public void visit(Circle circle) {
double area = Math.PI * circle.getRadius() * circle.getRadius();
totalArea += area;
System.out.println("Площадь круга: " + area);
}
@Override
public void visit(Rectangle rectangle) {
double area = rectangle.getWidth() * rectangle.getHeight();
totalArea += area;
System.out.println("Площадь прямоугольника: " + area);
}
public double getTotalArea() {
return totalArea;
}
}
// Пример использования
public class VisitorPatternExample {
public static void main(String[] args) {
Shape[] shapes = new Shape[]{
new Circle(5),
new Rectangle(4, 6)
};
AreaCalculator areaCalculator = new AreaCalculator();
for (Shape shape : shapes) {
shape.accept(areaCalculator);
}
System.out.println("Общая площадь: " + areaCalculator.getTotalArea());
}
}
Объяснение кода:
- Интерфейс
ShapeVisitor
определяет методыvisit
для каждого типа фигуры (круга и прямоугольника). - Интерфейс
Shape
определяет методaccept
, который принимает посетителя. - Классы
Circle
иRectangle
реализуют интерфейсShape
и определяют, как посетитель будет взаимодействовать с ними. - Класс
AreaCalculator
реализует интерфейсShapeVisitor
и определяет, как вычислять площадь для каждой фигуры. - В методе
main
мы создаем массив фигур и используемAreaCalculator
для вычисления их площадей.
Таким образом, паттерн "Посетитель" позволяет добавлять новые операции (например, вычисление площади) к объектам (фигурами) без изменения их классов. Это делает код более гибким и расширяемым, особенно когда количество операций может увеличиваться.