views:

86

answers:

3

Say I have a visitor like this

class Visitor : IVisitor
{
     void Accept(Visitable v)
     {
         /// other code
         v.AChild.Visit(this);
         v.BChild.Visit(this);
     }
}

Where AChild and BChild can be of the exact same type but the visiting code needs to differentiate between them (it needs to operate differently on AChild than BChild). What is the best way to do this?

  • set state in the visitor and check it on the next call
  • pass a different visitor to each child
  • other?


I'm sorry, I did that backwards the first time (The current Accept was Visit). It now matches the pattern as show in Wikipedia.

All visit methods look like this:

void Visit(IVisitor v) { v.Accept(this); }
A: 

Based on your architecture, you should just call v.Visit(this), and let your implementation of Visitable determine how to work with AChild and BChild.

Also, consider that AChild and BChild should probably be private members of your instance of Visitable.

David
see this question for a bit of background on my thinking: http://stackoverflow.com/questions/522803
BCS
IIRC how things are supposed to work, v.Visit(this) would be the code that got into my function
BCS
I gut Visit/accept backwards. please see edit
BCS
A: 

Given the following additional information from an answer in a background question by the Original Poster:

The visitor object is required to know the structure of the things it visits. That's OK, though. You're supposed to write specialized visit operations for each type of thing the visitor knows how to visit. This allows the visitor to decide how much it really wants to visit, and in what order.

I would answer: Create a special class of IVisitor, perhaps called ABChildVisitor, which would have a Visit() method that knows how to traverse AChild and BChild.

David
+1  A: 

You're still naming the methods backwards from the way I believe the pattern is traditionally used. Visitable (or Element) usually has an accept method and Visitor has a visitX method. I'm going to use the traditional naming scheme to avoid confusing myself :-)

IMO the easiest way to get this to work is by having multiple methods on your Visitor interface, one for each type of child. It doesn't matter if the children are the same language type or not, if they are semantically different they should be handled by different methods.

You should also try to avoid polluting the Visitor implementation with details about the structure of the Visitable. In order to do this I would move the accept method up into the Visitable interface instead of exposing childA and childB on that interface. Then each implementation of Visitable can decide which method on the visitor to call for each child. This communicates to the visitor all of the "location" context and gives you a nice, clean, decoupled solution.

Here's an example of what I'm thinking. Again, I've swapped the method names back to what I'm used to.

interface Visitable {
  accept(Visitor v)
}

interface Visitor {
  visitA(Node a)
  visitB(Node b)
}

class Container implements Visitable {
  private Node childA
  private Node childB

  ...
  void accept(Visitor v) {
    v.visitA(childA)
    v.visitB(childB)
  }
}

Now you get to have an implementation of Visitor that has 2 different methods, one for handling A children and one for handling B children.

Mike Deck
I had a mistake in my example, See edit :(
BCS
The point is Visitable should have an accept method (or in your case visit) in which it calls different methods on the visitor which give it the appropriate "location" context.
Mike Deck
I;m matching Wikipedia. Are we talking about the same thing?
BCS
The problem I'm trying to fix is that the called code is only a function of the type of the thing being visited and the things I'm looking at are of the same type
BCS