Visitor

From CSSEMediaWiki
(Difference between revisions)
Jump to: navigation, search
m (Reverted edits by Ebybymic (Talk); changed back to last version by Jenny Harlow)
 
(15 intermediate revisions by 8 users not shown)
Line 3: Line 3:
 
==Introduction==
 
==Introduction==
  
The Visitor is a [[Behavioural pattern|behavioural pattern]]. It allows the designer to define new operations on an object structure and its elements, without modifying the object structure itself.
+
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==
 
==Structure==
Line 15: Line 21:
  
 
Figure 1 graphically describes these Visitor pattern relationships.
 
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.
  
  
Line 24: Line 32:
  
 
*Sequence 1 - The object aVisitor1 performs an operation on anElementA
 
*Sequence 1 - The object aVisitor1 performs an operation on anElementA
*Sequence 2 - The object aVisitor2 performs an operation on anElementB
+
*Sequence 2 - The object aVisitor2 performs an operation on anElementA
*Sequence 3 - The object aVisitor1 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
 
*Sequence 4 - The object aVisitor2 performs an operation on anElementB
  
Line 36: Line 44:
 
#Visit across more than one class hierarchy
 
#Visit across more than one class hierarchy
 
===Liabilities===
 
===Liabilities===
#Adding a new ConreteElement is difficult
+
#Adding a new ConcreteElement is difficult
#Elements may expose otherwise private attributes
+
#'''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==
 
==Conflicts==
 
===The Acyclic Dependencies Principle===
 
===The Acyclic Dependencies Principle===
Line 44: Line 57:
 
*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.
 
*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.
 
*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==
 
==See also==
 
*[[A froggy visitor]]
 
*[[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.


Figure 1: A UML 2.1 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


Figure 2: A UML 2.1 communication diagram describing the interactions between objects in the Visitor pattern

Consequences

Benefits

  1. Adding new operations is easy. Just add a new Visitor class
  2. Separates unrelated behaviours and gathers related ones
  3. Visit across more than one class hierarchy

Liabilities

  1. Adding a new ConcreteElement is difficult
  2. 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.

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

See also


Personal tools