避免使用instanceof Patterns

时间:2014-11-26 12:03:05

标签: java oop design-patterns

我想避免使用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模块中。

是否有任何提示或提示(高级访客)或其他模式

4 个答案:

答案 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切换,但是......

干杯,