Based on the code I've found, it seems that the Visitor is required to known the structure of the visited objects and call on the needed children. This seems a bit clunky in some cases where the visitor would want to continue to work even if the visited classes are modified.
I guess the real question is: Is their a pattern where the enumeration is done by the visited code rather than the visitor code?
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.
Suppose you have a tree. One visitor might do a pre-order traversal, one might do an in-order traversal, and yet another visitor might act only on leaf nodes. The visitor classes can do all these things without requiring any changes to the tree class.
The visitor knows the structure, but that doesn't necessarily mean the operation the visitor performs knows all the structure. You might combine a visitor with a command. Give the visitor object a command object, and the visitor will invoke the command on each thing it visits.
If you want to have a simple operation and let the collection give you each item to act on, then you want the collection to provide an iterator for itself. Call your function on each thing the iterator gives you.
If you want to iterate over the tree's nodes in various orders, then the tree will need to offer multiple iterators. If you want to process nodes in an order that the tree doesn't already support, you'll need to modify the tree class.
Yes. The visited objects can do the enumeration (i.e. call on the needed children). This is still called the "Visitor" pattern (in fact, Design Pattern's first sample of Visitor does it this way). My made-up example snippet:
public void accept(Visitor visitor) {
for (Node n : children) {
n.accept(visitor);
}
}
Note: for visiting the children, we can't say visitor.visit(n);
. This is because Java does not dynamically select the method (based on the runtime class of its arguments), but selects the method statically (by the compile-time type of its arguments).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With