f76d8bc900689377724e6b9e83d8cbf3.ppt
- Количество слайдов: 27
Visitor Stéphane Ducasse stephane. ducasse@inria. fr http: //www. iam. unibe. ch/~ducasse/ Stéphane Ducasse 1
Visitor Intent: Represent an operation to be performed on the elements of an object structure in a class separate from the elements themselves. Visitor lets you define a new operation without changing the classes of the elements on which it operates. S. Ducasse 2
Visitor Possible Structure S. Ducasse 3
When to use a Visitor Whenever you have a number of items on which you have to perform a number of actions When you ‘decouple’ the actions from the items. Examples: the parse tree (Program. Node) uses a visitor for the compilation (emitting code on Code. Stream) Graphics. Context is a visitor for Visual. Components, Geometrics, and some other ones (Character. Array, . . . ) Rendering documents S. Ducasse 4
Applying the Visitor So all our problems are solved, no? Well. . . how to define it when to use a visitor control over item traversal choosing the granularity of visitor methods implementation tricks S. Ducasse 5
Visitor Toy Example Language to deal with arithmetic expressions. It supports one kind of number, and has +, *, (, ) We want to evaluate expressions, and print them. S. Ducasse 6
Example Evaluating 1+1 gives = 2 1 + (3 * 2) gives 7 Printing +1*32 S. Ducasse 7
Visitor Toy Example: Parse. Tree S. Ducasse 8
Expressions creation 1 ENumber value: 1 (3 * 2) Times left: (ENumber value: 3) right: (ENumber value: 2) 1 + (3 * 2) Plus left: (ENumber value: 1) right: (Times left: (ENumber value: 3) right: (ENumber value: 2)) Of course in Smalltalk we can just extend Number so no need of ENumber value: . . . S. Ducasse 9
Implementing the Actions Two solutions: add methods for evaluating, printing, . . . on Expression and its subclasses create a Visitor, add the visit methods on Expression and its subclasses, and implement visitors for evaluation, printing, . . . S. Ducasse 10
Visitor Toy Example Solution 1 S. Ducasse 11
Expressions creation (ENumber value: 1) evaluate >1 (Times left: (ENumber value: 3) right: (ENumber value: 2)) evaluate >6 (Plus left: (ENumber value: 1) right: (Times left: (ENumber value: 3) right: (ENumber value: 2))) evaluate >7 S. Ducasse 12
Limits of the approach printing is not easy may need specific instance variables adding it directly on Expression clutters Expression may need to add instance variables that are not part of the tree behavior of the printer are mixed with expressions S. Ducasse 13
Visitor Toy Example 2 S. Ducasse 14
Expressions creation Evaluator evaluate: (ENumber value: 1) >1 Evaluator evaluate: (Times left: (ENumber value: 3) right: (ENumber value: 2)) >6 Evaluator evaluate: (Plus left: (ENumber value: 1) right: (Times left: (ENumber value: 3) right: (ENumber value: 2))) >7 Evaluator>>evaluate: an. Expression ^ an. Expression accept. Visitor: self S. Ducasse 15
Evaluator>>visit. Number: a. Number ^ a. Number value Evaluator>>visit. Plus: an. Expression |l r| l : = an. Expression left accept. Visitor: self. r : = an. Expression right accept. Visitor: self. ^l+r Evaluator>>visit. Plus: an. Expression |l r| l : = an. Expression left accept. Visitor: self. r : = an. Expression right accept. Visitor: self. ^l*r S. Ducasse 16
Printer Visitor subclass: #Printer iv: ‘stream level’ Printer>>visit. Number: a. Number stream next. Put. All: a. Number value as. String Printer>>visit. Plus: an. Expression stream next. Put. All: ‘+’. an. Expression left accept. Visitor: self. an. Expression right accept. Visitor: self. Printer>>visit. Plus: an. Expression stream next. Put. All: ‘*’. an. Expression left accept. Visitor: self. an. Expression right accept. Visitor: self. S. Ducasse 17
Smalltalk’s class extensions Smalltalk has class extensions: method addition method replacement So ‘Decoupling’ actions from items can be done: e. g. , put all the printing methods together. take care: works only for methods makes it also really easy to package a visitor! Note: this is a static solution! S. Ducasse 18
Controlling the traversal Somewhere in the visitor, items are traversed. Different places where the traversal can be implemented: in the visitor on the items hierarchy S. Ducasse 19
Traversal on the Visitor S. Ducasse 20
Traversal on the Items S. Ducasse 21
Granularity of Visit Methods Sometimes you can represent contextual information by having more specialized visit methods So visitors have more information for implementing their operations S. Ducasse 22
Granularity of Visit Methods do. Node: is invoked from do. Variables: and do. Sequence: temporaries: statements: S. Ducasse 23
Refined Granularity Here do. Temporary. Variable: provides the context for treating do. Variable: S. Ducasse 24
Implementation Tricks You can implement it as we have shown before. But notice the general structure of the methods! This can be taken as advantage: code can be generated for a visitor. the method can be performed/invoked But take care: only works when there is a full correspondence. can make the code hard to understand. S. Ducasse 25
Using #perform: S. Ducasse 26
When to Use a Visitor: when the operations on items change a lot. Do not use a visitor: when the items you want to visit change a lot. Question: But how do we know what to choose upfront? S. Ducasse 27