I'm trying to create a messaging system in Java. I have an interface Message which will have multiple implementations (e.g. TextMessage and AudioMessage). This interface will be available on both the server and the client.
My problem is that the client should render different visual output based on the type of message it receives from the server. Therefore I either have to know the type of the message I'm dealing with which I could do using instanceof() or I can put an abstract method in the Message interface and make use of polymorphism so the Message takes care of creating the visual output.
However doing any of that feels dirty as I'd have to either create a new if instanceof block every time or let the Message take care of creating the visual part, which feels just as wrong, as it is supposed to be some kind of model.
Does anyone have a solution or an appropriate design pattern I could use here?
Thanks!
You can use Visitor Pattern for this.
interface Message{
public void accept(MessageVisitor visitor);
}
interface MessageVisitor{
public void visit(TextMessage message);
public void visit(AudioMessage message);
}
class PrintVisitor implements MessageVisitor{
public void visit(TextMessage message){
//print text message
}
public void visit(AudioMessage message){
//do step required
}
}
class TextMessage implements Message{
//other methods
public void accept(MessageVisitor visitor){
visitor.visit(this);
}
}
Using this double dispatch technique your instanceof
checks are not required. As well as the Printing logic goes out in the PrintVisitor
class, which allows for greater flexibility.
visitor.visit(this);
in this line you are calling visit
on visitor
with this
, now this
will use the actual type of instance, so the method of visitor
that will be called will be according to actual type.
Because now you can add new operations to your Message
class without changing the actual code of Message
using Visitor
s
Beware of some downfalls too. When your hierarchy of Message
changes it will cause change in all the Visitor
s. So do take care of that.
In Java, you should be looking at creating a Visitor type of pattern:
public interface MsgVisitor{
public Command handleMsg(FooMsg msg);
public Command handleMsg(BarMsg msg);
public Command handleMsg(BazMsg msg);
}
abstract class MyMessage{
public Command visit(MsgVisitor visitor){
return visitor.handleMsg(this);
}
}
and then you send what comes out of it down the pipeline so that the correct Command is tied to the correct message type.
The Command
(using the Command pattern) is what ties in what you need to do with the message and what it means. Therefore, this visitor just is there to assemble Commands
. It acts as a delegation point for actions. This allows you a richer way of handling and assembling hierarchy of logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With