Visitor Pattern in Java
Vicente Maldonado
Posted on March 23, 2019
When I find a concept difficult to understand I try to strip it to bare essentials. This happened to me recently with the visitor pattern so here is my take on it. Of course I will be grateful for any corrections. Here goes.
Let’s say we have three classes derived from a common parent, called A
abstract class A
{
public String name;
abstract void accept(Visitor v);
}
class B that has two objects as components:
class B extends A
{
public A child1;
public A child2;
public B(String name)
{
this.name = name;
}
[@Override](http://twitter.com/Override)
void accept(Visitor v)
{
v.visitB(this);
}
}
class C that has one component:
class C extends A
{
public A child;
public C(String name)
{
this.name = name;
}
[@Override](http://twitter.com/Override)
void accept(Visitor v)
{
v.visitC(this);
}
}
and class D that has no components
class D extends A
{
public D(String name)
{
this.name = name;
}
[@Override](http://twitter.com/Override)
void accept(Visitor v)
{
v.visitD(this);
}
}
All three classes expose a property, name that lets us distinguish their instances and a method named accept that allows visitors to visit them. The classes don’t care and don’t need to know what their visitors do. Visitor is an interface:
interface Visitor
{
public void visitB(B b);
public void visitC(C c);
public void visitD(D d);
}
There is a method for each class it visits. Let’s try this out with a visitor implementation that just prints out the name of objects it visited:
class PrintVisitor implements Visitor
{
public void visitB(B b)
{
b.child1.accept(this);
System.out.println(b.name + " visited.");
b.child2.accept(this);
}
public void visitC(C c)
{
System.out.println(c.name + " visited.");
c.child.accept(this);
}
public void visitD(D d)
{
System.out.println(d.name + " visited.");
}
}
The visitor is recursive: it visits a tree node and then it visits its children. Now let’s make a tree made up from the classes B, C and D:
/\*
F
/ \
B G
/ \ \
A D H
/ \ \
C E I
\*/
There are nine objects and seven relations. First, create the objects:
B f = new B("F");
B b = new B("B");
B d = new B("D");
C g = new C("G");
C h = new C("H");
D a = new D("A");
D c = new D("C");
D e = new D("E");
D i = new D("I");
Next, the relations:
f.child1 = b;
f.child2 = g;
b.child1 = a;
b.child2 = d;
d.child1 = c;
d.child2 = e;
g.child = h;
h.child = i;
And finally start visiting our tree by visiting its root node:
PrintVisitor v = new PrintVisitor();
f.accept(v);
The output is:
A visited.
B visited.
C visited.
D visited.
E visited.
F visited.
G visited.
H visited.
I visited.
If you look at this article, the above code performs tree traversal, and what is called in-order traversal at that (). Let’s change our visitor class to do a pre-order traversal — the visitor first displays the node name and then visits its children:
class PrintVisitor implements Visitor
{
public void visitB(B b)
{
System.out.println(b.name + " visited.");
b.child1.accept(this);
b.child2.accept(this);
}
public void visitC(C c)
{
System.out.println(c.name + " visited.");
c.child.accept(this);
}
public void visitD(D d)
{
System.out.println(d.name + " visited.");
}
}
Now the output is:
F visited.
B visited.
A visited.
D visited.
C visited.
E visited.
G visited.
H visited.
I visited.
In post-order traversal the visitor first visits node children and only then displays its name:
class PrintVisitor implements Visitor
{
public void visitB(B b)
{
b.child1.accept(this);
b.child2.accept(this);
System.out.println(b.name + " visited.");
}
public void visitC(C c)
{
c.child.accept(this);
System.out.println(c.name + " visited.");
}
public void visitD(D d)
{
System.out.println(d.name + " visited.");
}
}
Here is the output:
A visited.
C visited.
E visited.
D visited.
B visited.
I visited.
H visited.
G visited.
F visited.
Besides the Wikipedia article I linked at the beginning, there is a nice description of the visitor pattern here. In short:
- The visited objects don’t need to know what their visitors do, they just need to accept them.
- There needs to be a protocol that lets visited objects and visitors communicate, in our case the Visitor interface.
- A visitor uses separate methods (ie visitB, visitC and visitD for visiting each class)
(You can find the code on Github.)
Posted on March 23, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.