在阅读了一篇有趣的文章后,我对此有几个问题。请参阅常见陷阱#8:在[zero-turn-around]
上假装Java更像是C(即不理解OOP)我同意作者对陷阱的解决方案。我的代码遇到了类似的问题(滥用 instanceof )。但我无法按照作者的建议实现代码。我的方案如下
如果我同意作者的解决方案,我将不得不在Message类中实现特定于域的业务逻辑,我认为这会使我的轻量级消息对象膨胀。不仅如此,我现在在我的消息对象中有许多引用(组合),我认为这是不公平的,因为消息对象现在将具有业务(域)行为。
这个问题的合理解决方案是什么?下面的示例代码
public void onMessage(IMessage mssg)
{
if(mssg instanceof MoPn){
...
} else if(mssg instance of MoZn){
...
} else if(mssg instance of MoLn){
...
}
}
答案 0 :(得分:3)
一个合理的解决方案是创建知道使用特定类型消息的侦听器。
这是界面。
interface MessageListener<M extends IMessage> {
void onMessage(M message);
}
以下是其中一个类的骨架:
class MoZnListener implements MessageListener<MoZn> {
public void onMessage(MoZn message) {
}
}
现在,您可以在消息和侦听器之间创建映射。您可以使用属性文件,硬编码地图,注释。它是由你决定。一旦拥有它,您就可以实现一个看起来像
的JMS消息监听器class MessageEntryPoint implements MessageListener {
public void onMessage(Message message) {
getMessageHandler(message).onMessage(message.getObject());
}
}
现在你的系统是可以接受的。没有实例。要引入新的消息类型,您只需创建实现IMessage
的适当类和支持它的侦听器。
I
标记接口不是java风格。 MoPn
这样的名称可能会为您自行解释,但恕我直言,事实并非如此。尝试使用更多可自我解释的标识符。 答案 1 :(得分:3)
这可能会让一些纯粹主义者感到不安,但我相信使用具有OO功能的语言并不一定意味着您必须将OO应用于所有内容。
消息只是架构。他们携带数据。在仅仅将数据从一个地方传送到另一个地方的结构上强制面向对象也可以是反模式。
答案 2 :(得分:0)
将逻辑与数据模型分开有时被视为针对OOP,但有时需要进行解耦。发送消息的代码不需要知道如何响应消息。
instanceof的其他一些问题是,在添加新类型时很难找到需要更新的内容,并且无法确保涵盖所有案例。这些问题可以通过添加一些新接口来解决:
interface Message {
void callHandler(MessageHandler handler);
}
interface MessageHandler {
default void onMoPn(MoPn message) {
}
default void onMoZn(MoZn message) {
}
}
class MoPn implements Message {
public void callHandler(MessageHandler handler) {
handler.onMoPn(this);
}
}
class Mozn implements Message {
public void callHandler(MessageHandler handler) {
handler.onMoZn(this);
}
}
并添加处理程序:
class MessageHandlerImpl implements MessageHandler {
public void onMoPn(MoPn message) {
System.out.println("MoPn message: " + message);
}
}
收到消息后,您可以调用处理程序,如:
MessageHandler handler = new MessageHandlerImpl()
Message message = new MoPn();
message.callHandler(handler);