volker238 volker238 - 3 months ago 18
Java Question

Avoiding instanceof when checking a message type

I have the following situation where a client class executes different behavior based on the type of message it receives. I'm wondering if there is a better way of doing this since I don't like the instanceof and the if statements.

One thing I thought of doing was pulling the methods out of the client class and putting them into the messages. I would put a method like process() in the IMessage interface and then put the message specific behavior in each of the concrete message types. This would make the client simple because it would just call message.process() rather than checking types. However, the only problem with this is that the behavior contained in the conditionals has to do with operations on data contained within the Client class. Thus, if I did implement a process method in the concrete message classes I would have to pass it the client and I don't know if this really makes sense either.

public class Client {
messageReceived(IMessage message) {
if(message instanceof concreteMessageA) {
concreteMessageA msg = (concreteMessageA)message;
//do concreteMessageA operations
}
}
if (message instanceof concreteMessageB) {
concreteMessageb msg = (concreteMessageB)message;
//do concreteMessageB operations
}
}

Answer

The simple way to avoid instanceof testing is to dispatch polymorphicly; e.g.

public class Client {
    void messageReceived(IMessage message) {
        message.doOperations(this);
    }
}

where each message class defines an appropriate doOperations(Client client) method.

EDIT: second solution which better matches the requirements.

An alternative that replaces a sequence of 'instanceof' tests with a switch statement is:

public class Client {
    void messageReceived(IMessage message) {
        switch (message.getMessageType()) {
        case TYPE_A:
           // process type A
           break;
        case TYPE_B:
           ...
        }
    }
}

Each IMessage class needs to define an int getMessageType() method to return the appropriate code. Enums work just as well ints, and are more more elegant, IMO.