Visitor
(→Description) |
m (Reverted edits by Ebybymic (Talk); changed back to last version by Jenny Harlow) |
||
(23 intermediate revisions by 10 users not shown) | |||
Line 1: | Line 1: | ||
+ | [[Category:Design Patterns]] | ||
+ | [[Category:Behavioural Patterns]] | ||
==Introduction== | ==Introduction== | ||
− | The Visitor is a | + | The Visitor is a behavioral design pattern. It allows the designer to define new operations on an object structure and its elements, without modifying the object structure itself. |
− | == | + | ==Use When== |
+ | You should use the Visitor pattern when: | ||
+ | *An object structure contains many classes with different interfaces that you want to perform operations on depending on the concrete class of the objects. | ||
+ | *Many unrelated operations need to be performed on the parts of an object structure and you don't want to pollute the classes' interface by adding these operations. Visitor allows you to gather these operations in a separate class instead. | ||
+ | *The classes defining the object structure rarely change but you expect to frequently add new operations to be performed on them. | ||
− | The Visitor describes three distinct | + | ==Structure== |
− | * | + | |
+ | The Visitor describes the relations between three distinct classes: | ||
+ | |||
+ | *ObjectStructure - Provides a visitor with access to its elements | ||
*Element - Accepts visits. | *Element - Accepts visits. | ||
*Visitor - Accesses an element to perform operations. | *Visitor - Accesses an element to perform operations. | ||
+ | |||
+ | |||
Figure 1 graphically describes these Visitor pattern relationships. | Figure 1 graphically describes these Visitor pattern relationships. | ||
− | [[image:Visitor.JPG|frame|centre|'''Figure 1: A [[UML]] [[Class diagram|class diagram]] | + | |
+ | The Visitor pattern uses [[Double dispatch]] to reduce the coupling between the visitor and the object structure. | ||
+ | |||
+ | |||
+ | [[image:Visitor.JPG|frame|centre|'''Figure 1: A [[UML 2.1]] [[Class diagram|class diagram]] describing the Visitor structure''']] | ||
+ | |||
+ | ==Communication== | ||
+ | |||
+ | The Visitor pattern allows a visitor object to access and perform operations on an element object. A summary of the Visitor pattern communications is given in Fig. 2. Here the following interactions are shown: | ||
+ | |||
+ | *Sequence 1 - The object aVisitor1 performs an operation on anElementA | ||
+ | *Sequence 2 - The object aVisitor2 performs an operation on anElementA | ||
+ | *Sequence 3 - The object aVisitor1 performs an operation on anElementB | ||
+ | *Sequence 4 - The object aVisitor2 performs an operation on anElementB | ||
+ | |||
+ | |||
+ | [[image:VisitorCommunications.JPG|frame|centre|'''Figure 2: A [[UML 2.1]] [[Communication diagram|communication diagram]] describing the interactions between objects in the Visitor pattern''']] | ||
+ | ==Consequences== | ||
+ | ===Benefits=== | ||
+ | #Adding new operations is easy. Just add a new Visitor class | ||
+ | #Separates unrelated behaviours and gathers related ones | ||
+ | #Visit across more than one class hierarchy | ||
+ | ===Liabilities=== | ||
+ | #Adding a new ConcreteElement is difficult | ||
+ | #'''Elements may expose otherwise private attributes''' | ||
+ | |||
+ | == Example == | ||
+ | |||
+ | You can find [http://java.dzone.com/articles/design-patterns-visitor here] a nicely explained java code example of the Visitor Pattern usage in the real world. | ||
+ | |||
+ | ==Conflicts== | ||
+ | ===The Acyclic Dependencies Principle=== | ||
+ | The Visitor pattern conflicts with the [[Acyclic dependencies principle]]. Here, the concrete visitor depends on the interface of the concrete elements it visits. Similarly, the concrete elements must be familiar with interface of all visiting concrete visitors. | ||
+ | ====Mitigation==== | ||
+ | *Where a visitor pattern is necessary, the ill effects of cyclic dependency can be mitigated by ensuring that cyclically dependent classes are deployed within the same package. | ||
+ | *Bob Martin suggests a solution to this problem in his paper [http://www.objectmentor.com/resources/articles/acv.pdf Acyclic Visitor]. This solution uses casting to move the dependency from the interface of the concrete elements to the implementation. The abstract element is designed to depend on the abstract visitor, within a concrete element's implementation, down-casting is used to extract and consume the concrete visitor's interface. | ||
+ | |||
+ | ===Keep related data and behaviour in one place=== | ||
+ | The Visitor pattern deliberately violates Riel's heuristic [[Keep related data and behavior in one place]] by separating the desired behaviour from the data on which it operates. This means that getters and setters will need to be added to the object structure to allow the visitor to get at the data it needs. This is usually a sign that related data and behaviour is not kept in one place. Adding getters and setters to the object structure also violates related heuristics such as the [[Law of Demeter]] and [[Tell, don't ask]]. In addition, it compromises the encapsulation of data in the object structure, allowing access to this data not just from the visitor but from other parts of the system. | ||
+ | |||
+ | ===Coupling=== | ||
+ | The Visitor design pattern can lead to tight coupling between the visitor and the object structure. This happens because the behaviour has been separated from the data. | ||
+ | |||
+ | ==Related Patterns== | ||
+ | *[[Composite]]: Visitors can be useful to perform operations over a composite object structure. | ||
+ | *[[Interpreter]]: Visitors can be used to do the interpretation. | ||
+ | |||
+ | ==Conflicting Heuristics== | ||
+ | *[[Keep related data and behavior in one place]] | ||
+ | *[[Behavioral completeness]] | ||
+ | *[[Feature envy smell|Feature envy smell]] | ||
+ | *[[Tell, don't ask]] | ||
+ | |||
+ | ==See also== | ||
+ | *[[A froggy visitor]] | ||
+ | *[[Double dispatch]] | ||
+ | |||
+ | {{design patterns}} |
Latest revision as of 03:23, 25 November 2010
Contents |
Introduction
The Visitor is a behavioral design pattern. It allows the designer to define new operations on an object structure and its elements, without modifying the object structure itself.
Use When
You should use the Visitor pattern when:
- An object structure contains many classes with different interfaces that you want to perform operations on depending on the concrete class of the objects.
- Many unrelated operations need to be performed on the parts of an object structure and you don't want to pollute the classes' interface by adding these operations. Visitor allows you to gather these operations in a separate class instead.
- The classes defining the object structure rarely change but you expect to frequently add new operations to be performed on them.
Structure
The Visitor describes the relations between three distinct classes:
- ObjectStructure - Provides a visitor with access to its elements
- Element - Accepts visits.
- Visitor - Accesses an element to perform operations.
Figure 1 graphically describes these Visitor pattern relationships.
The Visitor pattern uses Double dispatch to reduce the coupling between the visitor and the object structure.
Communication
The Visitor pattern allows a visitor object to access and perform operations on an element object. A summary of the Visitor pattern communications is given in Fig. 2. Here the following interactions are shown:
- Sequence 1 - The object aVisitor1 performs an operation on anElementA
- Sequence 2 - The object aVisitor2 performs an operation on anElementA
- Sequence 3 - The object aVisitor1 performs an operation on anElementB
- Sequence 4 - The object aVisitor2 performs an operation on anElementB
Consequences
Benefits
- Adding new operations is easy. Just add a new Visitor class
- Separates unrelated behaviours and gathers related ones
- Visit across more than one class hierarchy
Liabilities
- Adding a new ConcreteElement is difficult
- Elements may expose otherwise private attributes
Example
You can find here a nicely explained java code example of the Visitor Pattern usage in the real world.
Conflicts
The Acyclic Dependencies Principle
The Visitor pattern conflicts with the Acyclic dependencies principle. Here, the concrete visitor depends on the interface of the concrete elements it visits. Similarly, the concrete elements must be familiar with interface of all visiting concrete visitors.
Mitigation
- Where a visitor pattern is necessary, the ill effects of cyclic dependency can be mitigated by ensuring that cyclically dependent classes are deployed within the same package.
- Bob Martin suggests a solution to this problem in his paper Acyclic Visitor. This solution uses casting to move the dependency from the interface of the concrete elements to the implementation. The abstract element is designed to depend on the abstract visitor, within a concrete element's implementation, down-casting is used to extract and consume the concrete visitor's interface.
The Visitor pattern deliberately violates Riel's heuristic Keep related data and behavior in one place by separating the desired behaviour from the data on which it operates. This means that getters and setters will need to be added to the object structure to allow the visitor to get at the data it needs. This is usually a sign that related data and behaviour is not kept in one place. Adding getters and setters to the object structure also violates related heuristics such as the Law of Demeter and Tell, don't ask. In addition, it compromises the encapsulation of data in the object structure, allowing access to this data not just from the visitor but from other parts of the system.
Coupling
The Visitor design pattern can lead to tight coupling between the visitor and the object structure. This happens because the behaviour has been separated from the data.
Related Patterns
- Composite: Visitors can be useful to perform operations over a composite object structure.
- Interpreter: Visitors can be used to do the interpretation.
Conflicting Heuristics
- Keep related data and behavior in one place
- Behavioral completeness
- Feature envy smell
- Tell, don't ask
See also
Design patterns | |
---|---|
Creational: Abstract Factory | Builder | Factory Method | Prototype | Singleton |