Why is it so hard to find a good example of a Visitor Pattern using Java 5 generics? All of the examples I’ve been able to find have been over complicated, too simplistic, or like in the Java Generics and Collections book; used to solve a completely different problem.
I should clarify my position on the Java Generics and Collections Visitor/Visitable example. The book shows an implementation meant to deal with parallel class hierarchies, which is not a common problem for most of us. It’s nice that that they provided an advanced example, but they failed to cover the simple case first. Don’t take this to mean that it’s a bad book. I still heartily recommend reading it
.
My criteria for a solid, re-usable Visitor and Visitable interface is relatively simple:
- Visitable classes can only accept Visitor’s of the same type (i.e., type-safe).
- Visitors can have a typed return value, no casting necessary.
Our Visitable interface needs to accept a type token defining the visitable class. When this is interface is implemented, the type token will end up referencing the implementing class -meaning the Visitable class can only ever accept Visitors implemented specifically for it. The #accept() method has a separate return value type that will be bound by the visitor.
The Visitor interface is much the same. It accepts a type token for the visitable class and a separate return type token. When implemented, the Visitor will define both what Visitable types it can be used with, and it’s own return type.
public interface Visitable<V> {
public <R> R accept(Visitor<V, R> visitor);
}
public interface Visitor<V, R> {
public R visit(V v);
}
It doesn’t look like much, in-fact it might not even make much sense until you see it in action. So without further ado, a (very) simple “Tree” class with children nodes.
public class Tree implements Visitable<Tree> {
private Integer id;
private Set<Tree> children = new HashSet<Tree>();
public Tree(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public Set<Tree> getChildren() {
return children;
}
public <R> R accept(Visitor<Tree, R> visitor) {
return visitor.visit(this);
}
}
Note that the implementation of the Visitable #accept() method will almost always have the same method body. You could very easily add an abstract class into the mix but we’ll leave that aside for now.
The Visitor is the fun bit. Below is a simple visitor that generates a string representing the entire tree. When the visitor is applied to a node, it will also visit all children of the node (and the children’s children, children’s children’s children etc.) collecting the ID of each.
public class ToStringTreeVisitor implements Visitor<Tree, String> {
public String visit(Tree tree) {
String str = getId() + ", ";
// visit all child nodes
for (Tree child : getChildren())
str += child.accept(this);
return str;
}
}
Tree root = new Tree(1);
root.getChildren().add(new Tree(2));
root.getChildren().add(new Tree(3));
String str = root.accept(new ToStringTreeVisitor());
// returns => "1, 2, 3"

Matt
/ February 3, 2011Nice!
that exactly what I was searching for. Other pages were either way too complex or just wrong.
Thanks!
Matt
/ February 3, 2011However.. i can’t see how to make it work with an abstract class. Like if Tree was abstract and that it had a class like ConcreteTree as child.. The problem is that children would be forced to implement
public R accept(Visitor visitor) {
return visitor.visit(this);
}
And the only function they could call on the Visitor would be visit(Tree).
How can we generalise the visitor in order that recieved visitor in the accept function provide the right function.
Brian Cowdery
/ February 3, 2011Your child would also have to extend from your abstract class. The entire point of the generic visitor is to ensure that you only accept visitors matching the type of your
Visitableclass.You can also use a interface as your visitor/visitable type which will let you use whatever child object you want providing it also implements the interface. Expose whatever methods you need to use when “visiting” as part of your interface so that you can avoid needing to cast objects in your visitor.
Something like:
public interface Tree {}public class AbstractTree implements Tree, implements Visitable<Tree> {
public R accept(Visitor visitor) { /* snip */ }
}
public class ConcreteChild implements Tree, Visitable<Tree> {
public R accept(Visitor visitor) { /* snip */ }
}
David
/ May 2, 2011I don’t get the benefit for the accept method to return an object.
In this article :
Java Visitor using Generics.You have another way to implement a typesafe visitor
Brian Cowdery
/ June 26, 2011True, the return value isn’t strictly necessary. You can simply add a member variable to your Visitor and gather your return value as you visit each node in the structure, however I’ve never liked that approach. In most of my use-cases I use the visitor as a way to transverse the structure and produce an output, not alter the structure itself – so for me having a return value is very important.
I also prefer my visitor instances to be re-usable so that I don’t have to create a new instance for every structure I want to examine (going through a list of account trees for example). If I was using a member variable in the visitor I wouldn’t be able to re-use it. Personally it’s just my style of coding to avoid unnecessary instance creation and to prefer return values over void methods that populate inner fields.
The article you’ve linked is new and It also looks like they’ve copied parts of my own, and still doesn’t solve my chief complaint about most of the generic visitor articles being over-complicated and hard to digest. Use what pattern you want in your own code, but make sure you have good reasons for your choice (Do I need a return value? Is this pattern saving me code or adding more? Does the type definition have to be that complicated?).
Cheers’