我想避免使用instanceof:
这是我的情况:
我的Events类的定义位于 commons模块:
中public class Event1 extends AbstractEvent{
}
public class Event2 extends AbstractEvent{
}
public class Event3 extends AbstractEvent{
}
在另一个名为jms的模块中我有一个侦听器从队列接收事件消息:
public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
// CONVERT message to Event Object
if (event instanceof Event1) {
// Execute Processing 1
}
if (event instanceof Event2) {
// Execute Processing 2
}
if (event instanceof Event3) {
// Execute Processing 3
}
}
我想避免使用instanceof
,这样做的最好方法是在execute
中使用AbstractEvent
方法的访问者模式,每个叶子类都会实现它。
我的问题是,在公共包中,我无权访问负责处理的类。 这些类仅存在于jms模块中。
是否有任何提示或提示(高级访客)或其他模式
答案 0 :(得分:2)
将所有可能的行为置于Map<Class, Runnable>
并匹配事件的类型和Runnable
类型。
答案 1 :(得分:1)
作为其他答案的替代方法,您可以将决策逻辑移动到您的消息传递配置中,以便MessageListener
专用于仅处理一种Event
类型的{{1}}消费每种类型的事件。这将从您的消费者中删除任何“if”逻辑。
这种方法的一个警告是,多个消费者可能无序处理事件。如果这是您的问题域的问题,您可能不希望自己处理无序问题。
有关详细信息,请参阅JMS Selectors
这种方法的优点是:
答案 2 :(得分:1)
在这种情况下,visitor Pattern有时会有所帮助。访问者模式主要适用于您的类层次结构没有太大变化,因为对于类层次结构中的每个更改,您还必须更改访问者(但如果您使用`instanceof&#39也是如此) ;)
要使用访问者模式,您需要定义一个Visitor
接口,其中包含您要访问的所有类型的访问方法:
interface Visitor {
visit(Event1 event);
visit(Event2 event);
visit(Event3 event);
}
首先,您需要一个公共超类,它是您要应用访问者的所有类的根。此超类包含方法callVisitor
:
public abstract class MyEvent extends AbstractEvent {
public abstract void visit(Visitor v);
}
public class Event1 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event1)
}
}
public class Event2 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event2)
}
}
public class Event3 extends MyEvent{
public void visit(Visitor v) {
v.visit(this); // calls visit(Event3)
}
}
最后,每次根据类的运行时类型需要不同的行为时,您都可以创建一个访问者实例:
public void onMessage(Message message) {
Visitor v = new Visitor() {
public void visit(Event1 event) {
// Execute Processing 1
}
public void visit(Event2 event) {
// Execute Processing 2
}
public void visit(Event3 event) {
// Execute Processing 3
}
}
event.visit(v);
}
访问者模式在您的情况下可能过度,但我发现它有时很有用。使用instanceof
和其他可能的解决方案的主要优点是它是类型安全的:如果向层次结构添加类,则在向所定义的所有访问者添加访问者方法之前,项目将不会编译。
答案 3 :(得分:0)
您可以让AbstractEvent声明一个抽象的isOfType()
方法:
public abstract class AbstractEvent {
public abstract boolean isOfType( String type );
}
它会消除instanceof
但不会if
切换,但是......
干杯,