Visitor Pattern
Visitor Pattern에 대해 설명하는 페이지입니다.
Visitor Pattern
Tags
Design Pattern, Java
1. Introduction
- Purpose
- Allowing one or more operations to be applied to a set of objects at runtime
- Decoupling the operations from the object structure (= the set of objects)
Info.
It's important that the visitor pattern is used when the above two purposes are needed.
- Use When
- An object structure must have many unrelated operations performed upon it
- The object structure can't change but operations on it can
- Operations must be performed on the concrete classes of an object structure
- Operations should be able to operate on multiple object structures that implement the same interface sets
2. Characteristics
- Pros
- Makes adding new operations easy
- You can define a new operation simply by adding a new visitor
- In contrast, if you spread functionality over many classes, then you must change each class to define a new operation
- Gathers related opertations and separates unrelated operations
- Related behavior is not spread over the classes defining the object structure; it’s localized in a visitor
- Unrelated sets of behavior are partitioned in their own visitor classes
- Makes adding new operations easy
- Cons
- Adding new ConcreteElement classes is hard
- The Visitor pattern makes it hard to add new subclasses of Element
- Each new ConcreteElement gives rise to a new abstract operation on Visitor and a corresponding implementation in every ConcreteVisitor class
- Breaking encapsulation
- Visitor’s approach assumes that the ConcreteElement interface is powerful enough to let visitors do their job
- The pattern often forces you to provide public operations that access an element’s internal state, which may compromise its encapsulation
- Adding new ConcreteElement classes is hard
- Visitors can visit objects that don't have a common parent class.
3. Participants
- Visitor
- declares a visit operation for each class of ConcreteElement in the object structure
- ConcreteVisitor
- implements each operation declared by Visitor
- Element
- defines an Accept operation that takes a visitor as an argument
- ConcreteElement
- implements an Accept operation that takes a visitor as an argument
- ObjectStructure
- can enumerate its elements
- may provide a high-level interface to allow the visitor to visit its elements
- may be a composite or a collection like a set or list
4. How to Use (Example)
-
Visitor
java1public interface ICarElementVisitor { 2 public void visit(Wheel wheel); 3 public void visit(Engine engine); 4 public void visit(Body body); 5 public void visit(Car car); 6} -
ConcreteVisitor
java1public class CarElementPrintVisitor implements ICarElementVisitor { 2 public void visit(Wheel wheel) { 3 System.out.println("Visiting " + wheel.getName() + " wheel"); 4 } 5 public void visit(Engine wheel) { 6 System.out.println("Visiting engine"); 7 } 8 public void visit(Body body) { 9 System.out.println("Visiting body"); 10 } 11 public void visit(Car car) { 12 System.out.println("Visiting car"); 13 } 14}java1public class CarElementDoVisitor implements ICarElementVisitor { 2 public void visit(Wheel wheel) { 3 System.out.println("Kicking my " + wheel.getName() + " wheel"); 4 } 5 public void visit(Engine wheel) { 6 System.out.println("Starting my engine"); 7 } 8 public void visit(Body body) { 9 System.out.println("Moving my body"); 10 } 11 public void visit(Car car) { 12 System.out.println("Starting my car"); 13 } 14} -
Element
java1public interface ICarElement { 2 public void accept(ICarElementVisitor visitor); 3} -
ConcreteElement
java1public class Wheel implements ICarElement { 2 private String name; 3 4 public Wheel(String name) { 5 this.name = name; 6 } 7 8 public String getName() { 9 return this.name; 10 } 11 12 @Override 13 public void accept(ICarElementVisitor visitor) { 14 visitor.visit(this); 15 } 16}java1public class Engine implements ICarElement { 2 @Override 3 public void accept(ICarElementVisitor visitor) { 4 visitor.visit(this); 5 } 6}java1public class Body implements ICarElement { 2 @Override 3 public void accept(ICarElementVisitor visitor) { 4 visitor.visit(this); 5 } 6}java1public class Car implements ICarElement { 2 private ICarElement[] elements; 3 public Car() { 4 this.elements = new ICarElement[] { 5 new Wheel("front left"), new Wheel("front right"), 6 new Wheel("back left") , new Wheel("back right"), 7 new Body(), new Engine() }; 8 } 9 public void accept(ICarElementVisitor visitor) { 10 for(ICarElement elem : elements) 11 elem.accept(visitor); 12 visitor.visit(this); 13 } 14}
