the visitor pattern (behavioral) ©softmoore consultingslide 1

23
The Visitor Pattern (Behavioral) ©SoftMoore Consulting Slide 1

Upload: luke-maxwell

Post on 21-Jan-2016

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

The Visitor Pattern(Behavioral)

©SoftMoore Consulting Slide 1

Page 2: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern: Basic Idea

• Provide an operation to be performed on the elements of a data structure (e.g., a list or tree) in another object.

• Visitor represents a kind of reversed encapsulation that separates an operation from its data.

Slide 2

Page 3: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Motivation

• Consider a compiler that parses a program and represents the parsed program as an abstract syntax tree (AST). The AST has many different kinds of nodes, such as Assignment, Variable Reference, and Arithmetic Expression nodes.

• Possible AST operations include:– checking that all variables are defined– checking for variables being assigned before they are used– type checking– code optimization– code generation– pretty printing/formatting

©SoftMoore Consulting Slide 3

Page 4: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Motivation(continued)

• These operations may need to treat each type of AST node differently. One approach would be to define each operation in the specific AST class.

©SoftMoore Consulting Slide 4

AST

checkConstraints()optimize()emitCode()

AssignmentStmt

checkConstraints()optimize()emitCode()

FunctionCall

checkConstraints()optimize()emitCode()

...

AddingExpr

checkConstraints()optimize()emitCode()

Page 5: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Motivation(continued)

• Problems with this approach:– Adding new operations requires changing/recompiling all of the

AST classes.– It can be confusing to have constraint-checking code mixed with

optimization code in the same class.

• An alternative solution is to encapsulate a desired operation in a separate object, called a visitor. The visitor object then traverses the elements of the AST. When an AST node “accepts” the visitor, it invokes a method on the visitor that includes the node type as an parameter. The visitor then executes the operation for that node – the operation that used to be in the AST node class.

©SoftMoore Consulting Slide 5

Page 6: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Motivation(continued)

©SoftMoore Consulting Slide 6

ASTVisitor

visitAssignmentStmt(AssignmentStmt)visitFunctionCall(FunctionCall)

ConstraintCheckVisitor

visitAssignmentStmt(AssignmentStmt)visitFunctionCall(FunctionCall)

OptimizeVisitor

visitAssignmentStmt(AssignmentStmt)visitFunctionCall(FunctionCall)

Page 7: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Motivation(continued)

©SoftMoore Consulting Slide 7

AST

accept(ASTVisitor)Program *

AssignmentStmt

accept(ASTVisitor v)

FunctionCall

accept(ASTVisitor v)

v.visitAssignmentStmt(this) v.visitFunctionCall(this)

Page 8: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Visitor Pattern

• Intent: Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Slide 8©SoftMoore Consulting

Page 9: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Applicability: Use the Visitor pattern when

• an object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes.

• many distinct and unrelated operations need to be performed on objects in an object structure. Visitor lets you keep operations together by defining them in one class.

• the classes defining an object structure rarely change, but you often want to define new operations over the structure.

Slide 9

Page 10: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Visitor Pattern(continued)

©SoftMoore Consulting Slide 10

Structure

Visitor

visitConcreteElementA(ConcreteElementA)visitConcreteElementB(ConcreteElementB)

ConcreteVisitor1

visitConcreteElementA(ConcreteElementA)visitConcreteElementB(ConcreteElementB)

ConcreteVisitor2

visitConcreteElementA(ConcreteElementA)visitConcreteElementB(ConcreteElementB)

Page 11: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Visitor Pattern(continued)

©SoftMoore Consulting Slide 11

Structure (continued)

Element

accept(Visitor)ObjectStructure *

ConcreteElementA

accept(Visitor v)operationA()

ConcreteElementB

accept(Visitor v)operationB()

v.visitConcreteElementA(this) v.visitConcreteElementB(this)

Page 12: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Participants

• Visitor– declares a visit() operation for each class of

ConcreteElement in the object structure. The operation’s name and signature identifies the class that sends the visit request to the visitor.

• ConcreteVisitor– implements each operation declared by Visitor. Each operation

implements a fragment of the algorithm defined for the corresponding class of object in the structure.

• Element– defines an accept() operation that takes a visitor as a

parameter.

Slide 12

Page 13: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Participants (continued)

• ConcreteElement– implements an accept() operation that takes a visitor as a

parameter.

• ObjectStructure– can enumerate/traverse its elements.– may provide a high-level interface to allow the visitor to visit its

elements.– may be either a composite or a collection such as a list or set.

Slide 13

Page 14: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Collaborations

• A client that uses the Visitor pattern must create a ConcreteVisitor object and then traverse the object structure, visiting each element with the visitor.

• When an element is visited, it calls the Visitor operation that corresponds to its class, supplying itself as an argument so that the visitor can access its state if necessary.

Slide 14

Page 15: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Slide 15

Collaborations (continued)

: ConcreteVisitor: ConcreteElementB: ObjectStructure

accept(Visitor)

: ConcreteElementA

visitConcreteEltA(this)

operationA()

accept(Visitor)

visitConcreteEltB(this)

operationB()

Page 16: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Consequences: The Visitor pattern

• Makes adding new operations easy. Visitors make it easy to add operations that depend on the components of complex objects. You can define a new operation over an object structure simply by adding a new visitor.

• Gathers related operations and separates unrelated ones. Related behavior isn’t spread over the classes that define the object structure; it’s localized in a visitor.

• Permits visiting across class hierarchies. In contrast to the Iterator pattern, visitors can visit objects that don’t have a common parent class; i.e., all objects in the structure are not required to have the same type.

Slide 16

Page 17: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Consequences: (continued)

• Makes adding a new ConcreteElement class hard. Each new ConcreteElement gives rise to a new operation on Visitor and a corresponding implementation in every ConcreteVisitor subclass. The key consideration in applying the Visitor pattern is the stability of the Element class hierarchy.– The Visitor pattern provides the most benefit when the class

hierarchy is stable but new operations need to be added or algorithms need to be changed.

– If the Element class hierarchy is changing frequently, then it’s probably easier just to define operations on the classes that make up the structure.

Slide 17

Page 18: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

Visitor Pattern(continued)

Consequences (continued)

• Permits accumulation of state information. A visitor can accumulate state information as it visits each element in the object structure, eliminating the need for extra parameters or global variables.

• Breaks encapsulation. Visitor’s approach assumes that the ConcreteElement interface is powerful enough to let visitors do their job. Otherwise, using a visitor could force you to compromise encapsulation.

Slide 18

Page 19: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Visitor Pattern(continued)

Implementation

• Double dispatch. Visitor lets you add operations to classes without changing them using a techniqueknown as double-dispatch.– single dispatch: The actual method invoked depends on the

method signature and the type of the receiver object.– double dispatch: The actual method invoked depends on the

method signature and the types of two receivers.– Operation accept() is a double-dispatch operation – the

operation that gets executed depends on both the type of Visitor and the type of Element it visits.

– Some languages (e.g., CLOS) support double-dispatch directly.

©SoftMoore Consulting Slide 19

Page 20: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Visitor Pattern(continued)

Implementation (continued)

• Who is responsible for traversing the object structure? The responsibility for traversal can be in any of three places.– the object structure (e.g., by having each accept() operation

traverse the elements children and call accept() on each of them recursively)

– the visitor (e.g., to implement a particularly complex traversal that depends on the results of operations on the object structure)

– in a separate iterator object

©SoftMoore Consulting Slide 20

Page 21: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Visitor Pattern in Java

• In package java.nio.file, support for the Visitor Pattern is provided by– the generic interface FileVisitor<T>– the generic class SimpleFileVisitor<T>

(which implements FileVisitor<T>)– static method Files.walkFileTree()

• Method Files.walkFileTree() walks a file tree rooted at a given starting file. The file tree traversal is depth-first with parameter FileVisitor invoked for each file encountered.

©SoftMoore Consulting Slide 21

Page 22: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

Related Patterns

• Visitors can be used to apply an operation over an object structure defined by the Composite pattern.

• Visitor may be applied to do the interpretation for the Interpreter pattern.

©SoftMoore Consulting Slide 22

Page 23: The Visitor Pattern (Behavioral) ©SoftMoore ConsultingSlide 1

©SoftMoore Consulting

References

• Visitor pattern (Wikipedia)https://en.wikipedia.org/wiki/Visitor_pattern

• Visitor Pattern (Object-Oriented Design)http://www.oodesign.com/visitor-pattern.html

• Visitor Design Pattern (SourceMaking)https://sourcemaking.com/design_patterns/visitor

• NIO.2 Cookbook, Part 3 by Jeff Friesen (JavaWorld)http://www.javaworld.com/article/2928805/core-java/nio-2-cookbook-part-3.html

• Visitor (dofactory)http://www.dofactory.com/net/visitor-design-pattern

Slide 23