Visitor pattern where the visitors choose how to traverse
Asked Answered
C

1

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.

Chablis answered 4/7, 2014 at 2:13 Comment(4)
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.Declamatory
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.Chablis
I found this article very interesting tech.puredanger.com/2007/07/16/visitor . Also see the discussion in the comments about where to put the "visiting logic".Declamatory
related question: #20045005Chablis
M
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.

Marmoset answered 6/7, 2014 at 1:2 Comment(4)
Thanks for the answer. Could you please elaborate or provide some links?Declamatory
@Declamatory I added some more detail for you.Marmoset
@Marmoset Should the traversal code mentioned in the answer be added in the base class of Visitees?Selfrespect
@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.Marmoset

© 2022 - 2024 — McMap. All rights reserved.