Java 避免使用instanceof模式

Java 避免使用instanceof模式,java,oop,design-patterns,Java,Oop,Design Patterns,我希望避免使用instanceof: 我的情况如下: my Events类的定义在公共模块中: public class Event1 extends AbstractEvent{ } public class Event2 extends AbstractEvent{ } public class Event3 extends AbstractEvent{ } 在另一个名为jms的模块中,我有一个从队列接收事件消息的侦听器: public class MyMessageListen

我希望避免使用instanceof:

我的情况如下:

my Events类的定义在公共模块中:

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
,最好的方法是在
AbstractEvent
中使用
execute
方法的访问者模式,每个叶类都将实现它

我的问题是,在公共包中,我无法访问负责处理的类这些类仅存在于jms模块中


是否有任何提示或提示(高级访客)或者另一种模式来实现这一点

将所有可能的行为放到
映射中
并匹配事件的类型和
可运行的类型。

将所有可能的行为放到
映射中
并匹配事件的类型和
可运行的类型。

您可以让AbstractEvent声明一个抽象的
isOfType()
方法:

public abstract class AbstractEvent {
    public abstract boolean isOfType( String type );
}
它将消除
实例,但不会消除
的if
切换


干杯,

您可以让AbstractEvent声明一个抽象的
isOfType()
方法:

public abstract class AbstractEvent {
    public abstract boolean isOfType( String type );
}
它将消除
实例,但不会消除
的if
切换


干杯,

作为其他答案的替代方法,您可以将决策逻辑移动到您的消息配置中,以便每种类型的事件都由一个专门处理一种类型的
事件的
消息侦听器使用。这将从您的消费者中删除任何“如果”逻辑

这种方法的一个警告是,多个使用者可能会无序处理事件。如果这是您的问题域的问题,您可能不希望自己处理顺序不一致的问题

有关更多信息,请参阅

这种方法的优点是:

  • 消费者只负责一种事件类型(简化)
  • 您可以根据事件类型(可伸缩性)独立添加更多使用者

作为其他答案的替代方法,您可以将决策逻辑移动到您的消息传递配置中,以便每种类型的事件都由一个专门处理一种类型的
事件的
消息侦听器使用。这将从您的消费者中删除任何“如果”逻辑

这种方法的一个警告是,多个使用者可能会无序处理事件。如果这是您的问题域的问题,您可能不希望自己处理顺序不一致的问题

有关更多信息,请参阅

这种方法的优点是:

  • 消费者只负责一种事件类型(简化)
  • 您可以根据事件类型(可伸缩性)独立添加更多使用者
在这种情况下,有时可以提供帮助。visitor模式主要适用于类层次结构变化不大的情况,因为对于类层次结构中的每次变化,您也必须更改visitor(但如果使用'instanceof'),情况也是如此

要使用访问者模式,您需要定义一个
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
和其他可能的解决方案相比,它的主要优点是类型安全:如果向层次结构中添加类,则在向定义的所有访问者添加访问者方法之前,项目将不会编译。

在这种情况下,该方法有时会有所帮助。visitor模式主要适用于类层次结构变化不大的情况,因为对于类层次结构中的每次变化,您也必须更改visitor(但如果使用'instanceof'),情况也是如此

要使用访问者模式,您需要定义一个
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
和其他可能的解决方案的主要优势在于它是类型安全的:如果您向层次结构中添加了一个类,那么项目将不会编译,直到您向定义的所有访问者添加了一个访问者方法。

请注意,要使其起作用,事件类必须是最终的,否则,子类可能无法被识别为其父类(反之亦然)。@Darkhogg取决于匹配算法。您可以使用
instanceof
、class equality或其他任何方法。请注意,要实现此功能,事件类必须是final,否则子类可能无法识别为其父类(反之亦然)。@Darkhogg取决于匹配算法。您可以使用
instanceof
、类相等或其他任何方法。我会将抽象方法添加到AbstractEvent,并将处理代码移动到events。我会将抽象方法添加到AbstractEvent,并将处理代码移动到events