jeudi 9 avril 2015

Refactoring the switch statements to polymorphic code

I have the functionality where my API sends out many types of messages, say, text image video audio and rich media contents. Each of them is sent out differently based on the type of provider (the one who provides a way to send out the messages). The API had the below design,



interface Response{
void sendTextMessage(String message);
void sendPictureMessage(byte[] image);
.....
void sendRichMediaMessage(RichMedia message);
}


This API has different implementations for different providers to process and send the message. But the real problem with this approach is, one provider provides new type of message whereas the old providers does not, so they need to implement the new method and throw UnsupportedOperationException. So I refactored it like the one below,



interface Response {
void sendMessage(ResponseMessage message);
}
abstract class ResponseMessage {
...
}
public class PlainTextResponse extends ResponseMessage {
private String message=message;
public PlainTextResponse(String message) {
this.message=message;
}
}


Now the client sends the message like,



public static void main(String... str) {
Response resp = ...;
resp.sendMessage(new PlainTextMessage("Hello World!!!");
}


Now implementing a Response interface



class ResponseProvider1Impl implement Response {
public ResponseProvider1Impl(ResponseProcessor processor) {
this.processor=processor;
}
void sendMessage(ResponseMessage message) {
processor.sendMessage(message);
}
}


I thought the ResponseProcessor would keep many things out from the actual Response interface



interface ResponseProcessor {
void sendMessage(ResponseMessage message)
void sendTextMessage(String message);
void sendPictureMessage(byte[] image);
.....
void sendRichMediaMessage(RichMedia message);
}


Things were going good till I got here,



class ResponseProcessorProvider1Impl implements ResponseProcessor {
.....
public void sendMessage(ResponseMessage message) {
// how do I get rid of this "if" blocks
if(message instanceof PlainTextMessage) {
sendTextMessage(message.getData());
} else if(message instanceof PictureMessage) {
sendTextMessage(message.getData());
}
}
....
}


Now the question: How do I get rid of the if blocks that checks and invokes methods based on its type? Yeah, I hear someone saying, move this to a factory with reflection or enum to not use switch or if statements, okay, but is that the right way for this? Do you see a better way to design this? any other design patterns I may apply for this?


Aucun commentaire:

Enregistrer un commentaire