我的功能是我的API发送许多类型的消息,比如文本图像视频音频和富媒体内容。根据提供者的类型(提供发送消息的方式),每个发送者的发送方式不同。 API具有以下设计,
interface Response{
void sendTextMessage(String message);
void sendPictureMessage(byte[] image);
.....
void sendRichMediaMessage(RichMedia message);
}
此API为不同的提供程序提供了不同的实现来处理和发送消息。但这种方法的真正问题是,一个提供者提供了新类型的消息,而旧提供者则没有,因此他们需要实现新方法并抛出UnsupportedOperationException
。所以我像下面那样重构它,
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;
}
}
现在客户端发送消息,如
public static void main(String... str) {
Response resp = ...;
resp.sendMessage(new PlainTextMessage("Hello World!!!");
}
现在实施一个Response接口
class ResponseProvider1Impl implement Response {
public ResponseProvider1Impl(ResponseProcessor processor) {
this.processor=processor;
}
void sendMessage(ResponseMessage message) {
// how do I get rid of this "if" block
if(message instanceof PlainTextMessage) {
processor.sendTextMessage(message.getData());
} else if(message instanceof PictureMessage) {
processor.sendPictureMessage(message.getData());
}
......
}
}
我认为ResponseProcessor会在实际的Response接口中保留很多东西
interface ResponseProcessor {
void sendTextMessage(String message);
void sendPictureMessage(byte[] image);
.....
void sendRichMediaMessage(RichMedia message);
}
直到我来到这里,事情才开始变得很好,
class ResponseProcessorProvider1Impl implements ResponseProcessor {
void sendTextMessage(String message){// do things to send a text message}
void sendPictureMessage(byte[] image){}
.....
void sendRichMediaMessage(RichMedia message){}
}
现在问题:如何摆脱根据其类型检查和调用方法的if块?是的,我听到有人说,把它移到有反射或枚举的工厂,不要使用开关或if语句,好吧,但这是正确的方法吗?你有没有看到更好的设计方法?我可以申请的任何其他设计模式吗?
答案 0 :(得分:0)
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());
}
}
....
}
你正在为每个类调用相同的方法,这里不需要任何开关(if,elseif)条件,只需直接放入
public void sendMessage(ResponseMessage message) {
// how do I get rid of this "if" blocks
sendTextMessage(message.getData());
}
即使在你需要调用另一个方法的情况下,我也会在每个类中创建一个方法,该方法具有相同的名称,可以调用正确的方法。
如果是这种情况,我会修改 PictureMessage , PlainTextMessage ,..类添加一个名为 sendMessage 的新方法,它将包含特定的每个类的代码,或者只是对特定方法的调用( sendPictureMessage , sendTexMessage ,...)
class PlainTextMessage->方法sendMessage->调用sendTextMessage
所以你可以保持接口总是调用sendMessage,无论类是什么。
答案 1 :(得分:0)
public class DDMain {
public static void main(String[] args) {
MsgSender sender = new Provider$ASender();
Resp resp = new RespImpl(sender);
resp.sendMsg(new TxtMsg("hello world"));
resp.sendMsg(new PicMsg(new byte[] { 'p', 'i', 'c' }));
}
}
interface Resp {
public void sendMsg(Msg msg);
}
class RespImpl implements Resp {
private MsgSender sender;
/**
*
*/
public RespImpl(MsgSender sender) {
this.sender = sender;
}
@Override
public void sendMsg(Msg msg) {
msg.sendWith(sender);
}
}
interface Msg {
byte[] getMsg();
void sendWith(MsgSender sender);
}
class TxtMsg implements Msg {
private String string;
/**
* @param string
*/
public TxtMsg(String string) {
this.string = string;
}
@Override
public void sendWith(MsgSender sender) {
sender.sendTxtMsg(this);
}
@Override
public byte[] getMsg() {
return string.getBytes();
}
}
class PicMsg implements Msg {
private byte[] data;
/**
*
*/
public PicMsg(byte[] data) {
this.data = data;
}
@Override
public void sendWith(MsgSender sender) {
sender.sendPictureMsg(this);
}
/*
* (non-Javadoc)
*
* @see mgage.ott.middleware.newspec.Msg#getMsg()
*/
@Override
public byte[] getMsg() {
return data;
}
}
interface MsgSender {
void sendTxtMsg(TxtMsg message);
void sendPictureMsg(PicMsg rectangle);
}
// this class stays protected and wouldn't be available outside the api.
class Provider$ASender implements MsgSender {
/**
*
*/
public Provider$ASender() {
// TODO Auto-generated constructor stub
}
@Override
public void sendTxtMsg(TxtMsg message) {
System.out.println("provider-A sending the txt message "
+ new String(message.getMsg()));
}
@Override
public void sendPictureMsg(PicMsg message) {
System.out.println("provider-A sending the pic message "
+ new String(message.getMsg()));
}
}