The Visitor Pattern is a behavioral design pattern that allows you to add new operations to objects without changing their structure. It separates an algorithm from the objects it operates on.
The Visitor Pattern involves two key elements:
- Visitor: Defines a set of operations to be performed on elements of an object structure.
- Element: Defines an
accept()
method that allows the visitor to access its data.
Key features:
- Open/Closed Principle: Allows adding new operations without modifying existing classes.
- Double Dispatch: Executes the operation on the visitor while providing access to the element's state.
- Extensibility: Supports adding new operations to existing structures.
- Extending Behavior: Add new operations without changing the classes of the elements.
- Separation of Concerns: Keeps the logic for specific operations separate from the elements.
- Consistency: Ensures operations are applied consistently across similar objects.
The implementation of the Visitor Pattern can be found in:
Figure.java
: Defines the base interface for figures.Circle.java
,Triangle.java
,Square.java
: Concrete elements implementing theaccept()
method.FigureVisitor.java
: Visitor interface defining operations for all figure types.HeightVisitor.java
,AreaVisitor.java
: Concrete visitors implementing specific behaviors.ObjectStructure.java
: Manages the collection of figures.Main.java
: Demonstrates the usage of the Visitor Pattern.
To see the Visitor Pattern in action, refer to the Main.java
file. It demonstrates how a collection of figures can be traversed, applying different visitor behaviors.
- Compilers:
- Applying different operations like code generation or optimization to syntax trees.
- Graphic Editors:
- Rendering, exporting, or analyzing shapes in an editor.
- File Systems:
- Performing operations like compression or indexing on files and folders.
classDiagram
direction LR
class Client {
}
class ObjectStructure {
}
class Element {
+Accept(Visitor)
}
class ElementA {
+Accept(v: Visitor)
}
class ElementB {
+Accept(v: Visitor)
}
class Visitor {
+VisitElementA(ElementA)
+VisitElementB(ElementB)
}
class ConcreteVisitor1 {
+VisitElementA(ElementA)
+VisitElementB(ElementB)
}
class ConcreteVisitor2 {
+VisitElementA(ElementA)
+VisitElementB(ElementB)
}
Client --> ObjectStructure
Client --> Visitor
ObjectStructure --> Element
Element <|-- ElementA
Element <|-- ElementB
Element --> Visitor
Visitor <|-- ConcreteVisitor1
Visitor <|-- ConcreteVisitor2
Note
If the UML above is not rendering correctly, you can view the diagram from the visitor_uml.png
file.
- The Visitor Pattern separates algorithms from the objects they operate on, adhering to the Open/Closed Principle.
- It’s ideal for applying operations to a collection of objects with varying types.
- Use it when you need to perform multiple unrelated operations on objects without modifying their structure.