检查消息类型时避免使用instanceof
我遇到以下情况,客户端类根据它收到的消息类型执行不同的行为。我想知道是否有更好的方法来做到这一点,因为我不喜欢 instanceof 和 if 语句。
我想做的一件事是将方法从客户端类中取出并将它们放入消息中。我会将类似 process() 的方法放入 IMessage 接口中,然后将消息特定行为放入每个具体消息类型中。这将使客户端变得简单,因为它只调用 message.process() 而不是检查类型。然而,唯一的问题是条件语句中包含的行为与 Client 类中包含的数据操作有关。因此,如果我确实在具体消息类中实现了一个处理方法,我就必须将它传递给客户端,而且我也不知道这是否真的有意义。
public class Client {
messageReceived(IMessage message) {
if(message instanceof concreteMessageA) {
concreteMessageA msg = (concreteMessageA)message;
//do concreteMessageA operations
}
}
if (message instanceof concreteMessageB) {
concreteMessageb msg = (concreteMessageB)message;
//do concreteMessageB operations
}
}
I have the following situation where a client class executes different behavior based on the type of message it receives. I'm wondering if there is a better way of doing this since I don't like the instanceof and the if statements.
One thing I thought of doing was pulling the methods out of the client class and putting them into the messages. I would put a method like process() in the IMessage interface and then put the message specific behavior in each of the concrete message types. This would make the client simple because it would just call message.process() rather than checking types. However, the only problem with this is that the behavior contained in the conditionals has to do with operations on data contained within the Client class. Thus, if I did implement a process method in the concrete message classes I would have to pass it the client and I don't know if this really makes sense either.
public class Client {
messageReceived(IMessage message) {
if(message instanceof concreteMessageA) {
concreteMessageA msg = (concreteMessageA)message;
//do concreteMessageA operations
}
}
if (message instanceof concreteMessageB) {
concreteMessageb msg = (concreteMessageB)message;
//do concreteMessageB operations
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
避免instanceof测试的简单方法是多态分派;例如,
每个消息类定义适当的 doOperations(Client client) 方法。
编辑:第二个解决方案更符合要求。
用 switch 语句替换一系列“instanceof”测试的替代方法是:
每个 IMessage 类都需要定义一个
int getMessageType()
方法来返回适当的代码。在我看来,枚举与整数一样工作,而且更优雅。The simple way to avoid instanceof testing is to dispatch polymorphicly; e.g.
where each message class defines an appropriate
doOperations(Client client)
method.EDIT: second solution which better matches the requirements.
An alternative that replaces a sequence of 'instanceof' tests with a switch statement is:
Each IMessage class needs to define an
int getMessageType()
method to return the appropriate code. Enums work just as well ints, and are more more elegant, IMO.这里的一个选项是处理程序链。您有一个处理程序链,每个处理程序都可以处理一条消息(如果适用),然后使用它,这意味着它不会在链中进一步传递。首先定义 Handler 接口:
然后处理程序链逻辑如下所示:
然后每个处理程序可以决定处理/使用事件:
当然,这并不能摆脱
instanceof
s - 但这确实意味着您没有巨大的if-elseif-else-if-instanceof
块,该块可能不可读One option here is a handler chain. You have a chain of handlers, each of which can handle a message (if applicable) and then consume it, meaning it won't be passed further down the chain. First you define the
Handler
interface:And then the handler chain logic looks like:
Then each handler can decide to handle / consume an event:
Of course, this doesn't get rid of the
instanceof
s - but it does mean you don't have a hugeif-elseif-else-if-instanceof
block, which can be unreadable您使用什么类型的消息系统?
许多人可以选择根据消息标题或内容向处理程序添加过滤器。如果支持这一点,您只需创建一个带有基于消息类型的过滤器的处理程序,那么您的代码就干净整洁,不需要instanceof或检查类型(因为消息系统已经为您检查了)。
我知道您可以在 JMS 或 OSGi 事件服务中执行此操作。
由于您使用的是 JMS,因此您基本上可以执行以下操作来注册侦听器。这将为每个独特的消息类型创建一个侦听器。
现在,每个处理程序将仅接收特定的消息类型(无 instanceof 或 if-then),当然假设发送者通过调用传出消息上的 setJMSType() 设置类型。
此方法内置于消息中,但您当然也可以创建自己的标头属性并对其进行过滤。
What type of message system are you using?
Many have options to add a filter to the handlers based on message header or content. If this is supported, you simply create a handler with a filter based on message type, then your code is nice and clean without the need for instanceof or checking type (since the messaging system already checked it for you).
I know you can do this in JMS or the OSGi event service.
Since you are using JMS, you can basically do the following to register your listeners. This will create a listener for each unique message type.
Now each handler will receive the specific message type only (no instanceof or if-then), assuming of course that the sender sets the type via calls to setJMSType() on the outgoing message.
This method is built into message, but you can of course create your own header property and filter on that instead as well.
使用双重调度的 Java 8 解决方案。没有完全摆脱
instanceof
但只需要对每条消息进行一次检查,而不是 if-elseif 链。A Java 8 solution that uses double dispatch. Doesn't get rid of
instanceof
completely but does only require one check per message instead of an if-elseif chain.对于 JMS 2.0,您可以使用:
有关更多信息,您可以参考 此处:
With JMS 2.0 you can use:
For more information you can refer here: