8

As I understand it, in the typical specification of the Visitor pattern, it is the visited objects that decide how to traverse, and generally, they only support one traversal order. (See, e.g., here or here.)

Is there a name for the same use of double-dispatch, but where the Visitors get to decide how to traverse the object-hierarchy? In my application, a very heterogeneous collection of document-model types is pushing towards visitors for, e.g., export operations. It seems rigid, though, to say that the various processors (visitors) should all traverse in, say, a breadth-first order. Some of them might only be concerned with a subset of the model or may need to deal with parts of the model in a specialized order.

I'm concerned about confusing other developers by using the names from the visitor pattern in a non-standard way. Is there a name for what I'm suggesting?

I'll also ask if there's a reason not to let the visitor control traversal, just in case there's some wisdom in that usual Visitor formulation that I'm missing. The application is in Java if that may be relevant.

Majid Ali Khan
  • 701
  • 8
  • 13
Joshua Goldberg
  • 5,059
  • 2
  • 34
  • 39
  • How did you solve this problem? IMO if we let the Visitor call the "accept" methods (i.e., the visitor choose the traversal order) we go totally against the pattern, because when we change the implementation of the "visiting" object we will need to change the visitor altogether. – JohnTortugo Nov 29 '14 at 20:07
  • I found that for my use-cases there was little enough overlap between the various functions traversing the model that the abstraction was unhelpful. For instance, some functions needed to return on or another kind of data at various stages of the computation, some needed multiple arguments of various sorts passed around, etc. – Joshua Goldberg Nov 30 '14 at 02:04
  • 2
    I found this article very interesting http://tech.puredanger.com/2007/07/16/visitor/ . Also see the discussion in the comments about where to put the "visiting logic". – JohnTortugo Nov 30 '14 at 02:32
  • related question: https://stackoverflow.com/questions/20044505/visitor-pattern-traversing-tree-elements-in-client-or-visitor – Joshua Goldberg Oct 15 '15 at 17:20

1 Answers1

4

To keep the design clear, you can encapsulate traversal logic in an Iterator. The visitor or visitees can use the iterator to determine the next node to visit.

In the Visitor example on wikipedia, we see the class Car control the order of visiting as follows:

public void accept(ICarElementVisitor visitor) {    
    for(ICarElement elem : elements) {
        elem.accept(visitor);
    }
    visitor.visit(this);    
}

It would be easy to encapsulate the traversal logic in an ICarElementIterator that returns an ICarElement from its next() method, per the Iterator pattern.

Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
  • Thanks for the answer. Could you please elaborate or provide some links? – JohnTortugo Nov 29 '14 at 20:03
  • @JohnTortugo I added some more detail for you. – Fuhrmanator Nov 30 '14 at 00:59
  • @Fuhrmanator Should the traversal code mentioned in the answer be added in the base class of Visitees? – V K Jun 06 '19 at 04:13
  • @VK I would put it where it makes sense in terms of cohesion. That is, if the traversal logic is really part of the structure, then put it there. If it's part of a visitor's particular functionality (i.e., the traversal order depends on the function provided by the visitor), then put it in the visitor. – Fuhrmanator Mar 16 '21 at 16:06