DEV Community

Vicente Maldonado
Vicente Maldonado

Posted on • Originally published at Medium on

Visitor Pattern in Java

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); } 
Enter fullscreen mode Exit fullscreen mode

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); } } 
Enter fullscreen mode Exit fullscreen mode

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); } } 
Enter fullscreen mode Exit fullscreen mode

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); } } 
Enter fullscreen mode Exit fullscreen mode

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); } 
Enter fullscreen mode Exit fullscreen mode

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."); } } 
Enter fullscreen mode Exit fullscreen mode

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 \*/ 
Enter fullscreen mode Exit fullscreen mode

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"); 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

And finally start visiting our tree by visiting its root node:

 PrintVisitor v = new PrintVisitor(); f.accept(v); 
Enter fullscreen mode Exit fullscreen mode

The output is:

A visited. B visited. C visited. D visited. E visited. F visited. G visited. H visited. I visited. 
Enter fullscreen mode Exit fullscreen mode

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."); } } 
Enter fullscreen mode Exit fullscreen mode

Now the output is:

F visited. B visited. A visited. D visited. C visited. E visited. G visited. H visited. I visited. 
Enter fullscreen mode Exit fullscreen mode

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."); } } 
Enter fullscreen mode Exit fullscreen mode

Here is the output:

A visited. C visited. E visited. D visited. B visited. I visited. H visited. G visited. F visited. 
Enter fullscreen mode Exit fullscreen mode

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.)

Top comments (0)