DEV Community

loading...

Visitor Pattern in Java

vicentemaldonado profile image Vicente Maldonado Originally published at Medium on ・3 min read

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

Discussion (0)

pic
Editor guide