Avoiding instanceof in Java

Each event has a function, say do. Each subclass overrides do, to do (:P) the appropriate action. Dynamic dispatch does everything else afterwards. All you need to do, is call event.do()


The simplest approach is to have the Event provide a method you can call so the Event knows what to do.

interface Event {
    public void onEvent(Context context);
}

class DocumentEvent implements Event {
    public void onEvent(Context context) {
         context.getDocumentGenerator().gerenateDocument(this);
    }
}

class MailEvent implements Event {
    public void onEvent(Context context) {
         context.getDeliveryManager().deliverMail(event);
    }
}


class Context {
    public void divideEvent(Event event) {
        event.onEvent(this);
    }
}

Polymorphism is your friend.

class DocumentGenerator {
   public void generate(DocumentEvent ev){}
   public void generate(MainEvent ev){}
   //... and so on
}

Then just

 DocumentGenerator dg = new DocumentGenerator();

 // ....
 dg.generate(event);

Update

A number of people have raised the objection that you "have to know the kinds of event at compile time." And, yes, you clearly have to know what events you're interpreting at compile time of the generator part, when else would you be able to write the generating part?

These competing examples use Command pattern, which is fine, but means Events have to know the details not just of their representation but of how to print their representation. That means each class may have two kinds of requirements changes to which their sensitive: changes in what events represent, and changes in the way the events are represented in print.

Now, consider, for example, needing to internationalize this. In the Command-pattern case, you have to go to n classes for n different Event types and write new do methods. In the polymorphism case, the changes are localized to one class.

Naturally if you need to internationalize once, you may need many languages, which drive you to adding something like a Strategy to each class in the Command-pattern case, requiring now n classes × m languages; again, you need only have one strategy and one class in the polymorphism case.

There are reasons to choose either approach, but to claim the polymorphism approach is wrong is just incorrect.