Visitor Pattern in Java

vicentemaldonado

Vicente Maldonado

Posted on March 23, 2019

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

💖 💪 🙅 🚩
vicentemaldonado
Vicente Maldonado

Posted on March 23, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Visitor Pattern in Java
datastructures Visitor Pattern in Java

March 23, 2019