🤖📘🍻 Hooray! After 3 years of work, we've finally released a new ebook on design patterns! Check it out »

Visitor Design Pattern in Java

Visitor-Composite

Discussion. We would like to declare a function like: void process( virtual Base object1, virtual Base object2 ) that does the right thing based on the type of 2 objects that come from a single inheritance hierarchy. The only problem is that the keyword “virtual” may not be used to request dynamic binding for an object being passed as an argument. Java will only “discriminate” the type of an object being messaged, not the type of an object being passed.

So in order for the type of 2 objects to be discriminated, each object must be the receiver of a virtual function call. Here, when process1() is called on the first object, its type becomes “known” at runtime, but the type of the second is still Unknown. process2() is then called on the second object, and the identity (and type) of the first object is passed as an argument. Flow of control has now been vectored to the spot where the type (and identity) of both objects are known.

interface Base {
    void execute(Base target);
    void doJob(FOO target);
    void doJob(BAR target);
    void doJob(BAZ target);
}

class FOO implements Base {
    public void execute(Base base) {
        base.doJob(this);
    }

    public void doJob(FOO foo) {
        System.out.println("FOO object calls by yourself");
    }

    public void doJob(BAR bar) {
        System.out.println("BAR object was called from FOO");
    }

    public void doJob(BAZ baz) {
        System.out.println("BAZ object was called from FOO");
    }
}

class BAR implements Base {
    public void execute(Base base) {
        base.doJob(this);
    }

    public void doJob(FOO foo) {
        System.out.println("FOO object was called from BAR" );
    }

    public void doJob(BAR bar) {
        System.out.println("BAR object calls by yourself");
    }

    public void doJob(BAZ baz) {
        System.out.println("BAZ object was called from BAR");
    }
}

class BAZ implements Base {
    public void execute(Base base) {
        base.doJob( this);
    }

    public void doJob(FOO foo) {
        System.out.println("FOO object was called from BAZ");
    }

    public void doJob(BAR bar) {
        System.out.println("BAR object was called from BAZ");
    }

    public void doJob(BAZ baz) {
        System.out.println("BAZ object calls by yourself");
    }
}

public class VisitorDemo {
    public static void main(String[] args) {
        Base objects[] = {new FOO(), new BAR(), new BAZ()};
        for (Base object : objects) {
            for (int j = 0; j < 3; j++) {
                object.execute(objects[j]);
            }
            System.out.println();
        }
    }
}

Output

FOO object calls by yourself
FOO object was called from BAR
FOO object was called from BAZ

BAR object was called from FOO
BAR object calls by yourself
BAR object was called from BAZ

BAZ object was called from FOO
BAZ object was called from BAR
BAZ object calls by yourself

Code examples

More info, diagrams and examples of the Visitor design pattern you can find on our new resource Refactoring.Guru.