Reputation: 36984
I have 2 applications: application_1
and applicaion_2
appplication_1
sends messages of different types to application_2
there several types. I can declare enum of these types.
enum MessageType{
TYPE_1,
TYPE_2,
...
}
In application_2 framework I use suggest me write following API
public void handle(Object o){
//logic
}
I think about how to build classes to process each message separately.
I understand that I can declare common type for all messages:
abstract class AbstractMessage{
MessageType type;
Object o;
//...
}
and in application_2
inside handle I can write smth like this:
MessageType mt = ((AbstractMessage) o).getType();
switch(mt){
case TYPE_1:
//handle TYPE_1
break;
case TYPE_2:
//handle TYPE_2
break;
....
}
But this code looks ugly.
Please, help to find nicer solution.
Upvotes: 3
Views: 1656
Reputation: 10003
maybe something like below. it does have a switch, but the code for each type is together in the enum.
public class So43459907 {
public enum Type {
m1 {
@Override Object create(Object o) {
return o;
}
@Override void handle(Object o) {}
},
m2 {
@Override Object create(Object o) {
return o;
}
@Override void handle(Object o) {}
};
abstract Object create(Object o);
abstract void handle(Object o);
public static Object create(Type type,Object o) {
switch(type) {
case m1:
return m1.create(o);
case m2:
return m2.create(o);
default:
throw new RuntimeException("oops");
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Upvotes: 0
Reputation:
You can use the chain-of-responsibility pattern. It differs from the strategy pattern in that your messages are indicating commands that each application performs. This is essentially what switch
is doing.
You dynamically load classes that implement an interface with your handle
method (Pavlo's class works with some modification to combine it with Loris' abstract message):
public interface MessageHandler
{
void handle (AbstractMessage msg);
}
Java has the concept of a service provider that is one method for dynamic loading (I'm sure there are other methods that can be used if this doesn't fit your need). You can iterate through the handlers at the time the message is handled, passing each handler the message instance. Each handler decides if it wants to handle the message or not. You could even make handle
return a boolean
to indicate that the chain can stop calling subsequent handlers if you so wish.
You can implement handlers in each application for the message types you want to handle. There are many ways to go about this (load the handlers and initialize each at startup, load them at time of message handling, etc) so pick the one that fits your need. The linked service providers article has a simple loop demonstrating the loading of the handlers.
No need for a switch
that changes as your code is modified, you just reconfigure how your jar is built. This is also a good example of the open-closed principle where your code does not change but is open to extension.
Upvotes: 0
Reputation: 7638
If you want to use polymorfism you could define the abstract
message class:
abstract class AbstractMessage {
public abstract void doStuff();
//...
}
instead of using enums
, create a class for each message type extending the abstract class and overriding the methods:
class Type1Message extends AbstractMessage {
@Override
public void doStuff() {
//handle TYPE_1
}
}
class Type2Message extends AbstractMessage {
@Override
public void doStuff() {
//handle TYPE_2
}
}
then in your handle
method:
((AbstractMessage) o).doStuff();
Upvotes: 4
Reputation: 937
application_2
anyway will need to know which type of message it has received, so some kind of switch
is unavoidable. But the key thing is to have this switch
only at one place. For example, you could have method like following:
public MessageHandler getHandlerFor(MessageType messageType) {
switch (messageType) {
case TYPE_1: return Type1MessageHandler();
case TYPE_2: return Type2MessageHandler();
............
default: throw new IllegalArgumentException("No handler found for messageType: " + messageType);
}
}
Then you will need the hierarchy of MessageHandler
's which correspond to strategy pattern:
public interface MessageHandler {
void handle();
}
Each implementation of MessageHandler
interface should provide MessageType
-specific handling logic.
Upvotes: 0