如何用多态替换开关?

时间:2017-04-17 21:26:11

标签: java oop design-patterns enums polymorphism

我有2个应用程序:application_1applicaion_2

appplication_1将不同类型的邮件发送到application_2

有几种类型。我可以声明这些类型的枚举。

enum MessageType{
   TYPE_1,
   TYPE_2,
   ...
}

在application_2框架中,我建议我编写以下API

public void handle(Object o){
    //logic
}

我考虑如何构建类来分别处理每个消息。

我知道我可以为所有消息声明公共类型:

abstract class AbstractMessage{
    MessageType type;
    Object o; 
    //...   
}

并且在application_2内部句柄中我可以像这样编写smth:

MessageType mt = ((AbstractMessage) o).getType();
  switch(mt){
     case TYPE_1: 
        //handle TYPE_1
        break;
     case TYPE_2: 
        //handle TYPE_2
        break;
        ....
  }

但这段代码看起来很难看。

请帮助找到更好的解决方案。

4 个答案:

答案 0 :(得分:4)

如果您想使用多态性,您可以定义MessageType消息类:

abstract

而不是使用abstract class AbstractMessage { public abstract void doStuff(); //... } ,为扩展抽象类并覆盖方法的每种消息类型创建一个类:

enums

然后在您的class Type1Message extends AbstractMessage { @Override public void doStuff() { //handle TYPE_1 } } class Type2Message extends AbstractMessage { @Override public void doStuff() { //handle TYPE_2 } } 方法中:

handle

答案 1 :(得分:0)

application_2无论如何都需要知道它收到了哪种类型的消息,因此某种switch是不可避免的。但关键是只在一个地方{/ 1}} 。例如,您可以使用以下方法:

switch

然后您将需要public MessageHandler getHandlerFor(MessageType messageType) { switch (messageType) { case TYPE_1: return Type1MessageHandler(); case TYPE_2: return Type2MessageHandler(); ............ default: throw new IllegalArgumentException("No handler found for messageType: " + messageType); } } 的层次结构,其对应于策略模式:

MessageHandler

public interface MessageHandler { void handle(); } 接口的每个实现都应该提供MessageHandler特定的处理逻辑。

答案 2 :(得分:0)

您可以使用chain-of-responsibility模式。它与策略模式的不同之处在于,您的消息指示每个应用程序执行的命令。这基本上是switch正在做的事情。

使用handle方法动态加载实现接口的类(Pavlo的类可以进行一些修改以将其与Loris的抽象消息结合起来):

public interface MessageHandler
{
  void handle (AbstractMessage msg);
}

Java具有service provider的概念,这是动态加载的一种方法(我确信如果这不符合您的需要,还可以使用其他方法)。您可以在处理消息时迭代处理程序,将每个处理程序传递给消息实例。每个处理程序决定是否要处理该消息。你甚至可以让handle返回boolean来表明如果你愿意,链可以停止调用后续的处理程序。

您可以在每个应用程序中为要处理的消息类型实现处理程序。有很多方法可以解决这个问题(加载处理程序并在启动时初始化每个方法,在处理消息时加载它们等等),所以选择一个适合您需要的方法。链接服务提供者文章有一个简单的循环,演示了处理程序的加载。

修改代码时不需要更改switch,只需重新配置jar的构建方式即可。这也是open-closed principle的一个很好的示例,您的代码不会更改,但可以扩展。

答案 3 :(得分:0)

可能就像下面这样。它确实有一个开关,但每种类型的代码都在枚举中。

public class So43459907 {
    public enum Type {
        m1 {
            @Override Object create(Object o) {
                return o;
            }
            @Override void handle(Object o) {}
        },
        m2 {
            @Override Object create(Object o) {
                return o;
            }
            @Override void handle(Object o) {}
        };
        abstract Object create(Object o);
        abstract void handle(Object o);
        public static Object create(Type type,Object o) {
            switch(type) {
                case m1:
                    return m1.create(o);
                case m2:
                    return m2.create(o);
                default:
                    throw new RuntimeException("oops");
            }
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
    }
}