Visitor Pattern = Tách các thao tác (operations) ra khỏi cấu trúc object (object structure) → để bạn có thể thêm hành vi mới mà không sửa class hiện tại
Ý tưởng cốt lõi
Bạn có
- Một tập object ổn định (ít thay đổi)
- Nhưng logic xử lý trên chúng thay đổi thường xuyên
Cách hoạt động (Double Dispatch)
Visitor dùng kỹ thuật: Double Dispatch → chọn method dựa trên:
- Loại Visitor
- Loại Element
Example:
Bài toán: Share (Circle, Rectagle) + nhiều operation
1. Element interface
interface Shape {
void accept(ShapeVisitor visitor);
}
2. Concrete Elements
class Circle implements Shape {
public void accept(ShapeVisitor visitor) {
visitor.visit(this);
}
}
class Rectangle implements Shape {
public void accept(ShapeVisitor visitor) {
visitor.visit(this);
}
}
3. Visitor interface
interface ShapeVisitor {
void visit(Circle circle);
void visit(Rectangle rectangle);
}
4. Concrete Visitor – Draw
class DrawVisitor implements ShapeVisitor {
public void visit(Circle circle) {
System.out.println("Drawing Circle");
}
public void visit(Rectangle rectangle) {
System.out.println("Drawing Rectangle");
}
}
5. Concrete Visitor – Area
class AreaVisitor implements ShapeVisitor {
public void visit(Circle circle) {
System.out.println("Calculating Circle area");
}
public void visit(Rectangle rectangle) {
System.out.println("Calculating Rectangle area");
}
}
Usage
public class Main {
public static void main(String[] args) {
Shape[] shapes = { new Circle(), new Rectangle() };
ShapeVisitor draw = new DrawVisitor();
ShapeVisitor area = new AreaVisitor();
for (Shape shape : shapes) {
shape.accept(draw);
shape.accept(area);
}
}
}
Output
Drawing Circle
Calculating Circle area
Drawing Rectangle
Calculating Rectangle area
Điểm quan trọng
- accept(visitor)
- Là điểm “hook”
- Cho phép Visitor truy cập object
- Visitor = tập hợp operations
- Mỗi visitor = 1 loại logic
- Draw
- Export
- Validate
- Pricing
- Thêm behavior cực dễ
Thêm class mới mà không cẩn sửa Circle, Rectangle
class ExportVisitor implements ShapeVisitor { ... }
Nhược điểm (rất quan trọng)
- ❗ Thêm class mới (Element) → phải sửa tất cả Visitor
- ❗ Khá phức tạp (double dispatch)
- ❗ Vi phạm OCP theo chiều ngược