How to avoid large if-statements and instanceof

An elegant way of avoiding instanceof without inventing some new artificial method in the base class (with a non-descriptive name such as performAction or doWhatYouAreSupposedToDo) is to use the visitor pattern. Here is an example:

Animal

import java.util.*;

abstract class Animal {
    String name;

    public Animal(String name) {
        this.name = name;
    }

    public abstract void accept(AnimalVisitor av);  // <-- Open up for visitors.

}

Lion and Deer

class Lion extends Animal {
    public Lion(String name) {
        super(name);
    }
    public void roar() {
        System.out.println("Roar");
    }

    public void accept(AnimalVisitor av) {
        av.visit(this);                            // <-- Accept and call visit.
    }
}


class Deer extends Animal {

    public Deer(String name) {
        super(name);
    }

    public void runAway() {
        System.out.println("Running...");
    }

    public void accept(AnimalVisitor av) {
        av.visit(this);                            // <-- Accept and call visit.
    }

}

Visitor

interface AnimalVisitor {
    void visit(Lion l);
    void visit(Deer d);
}

class ActionVisitor implements AnimalVisitor {

    public void visit(Deer d) {
        d.runAway();
    }

    public void visit(Lion l) {
        l.roar();
    }
}

TestAnimals

public class TestAnimals {
    public static void main(String[] args) {
        Animal lion = new Lion("Geo");
        Animal deer1 = new Deer("D1");
        Animal deer2 = new Deer("D2");

        List<Animal> li = new ArrayList<Animal>();
        li.add(lion);
        li.add(deer1);
        li.add(deer2);
        for (Animal a : li)
            a.accept(new ActionVisitor());         // <-- Accept / visit.
    }
}

Leave a Comment