如何用多态性替换开关



我有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;
        ....
  }

但是这个代码看起来很丑。

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

如果要使用polymorfism,则可以定义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方法中:

((AbstractMessage) o).doStuff();

application_2无论如何都需要知道它已收到的消息类型,因此不可避免的是某种switch。但是,关键是只在一个地点 让此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接口的每个实现都应提供MessageType-特定处理逻辑。

您可以使用责任链模式。它与策略模式不同,因为您的消息指示每个应用程序执行的命令。从本质上讲,这是switch正在做的。

您动态加载了与您的handle方法实现接口的类(Pavlo的类一起使用一些修改,将其与Loris的抽象消息结合在一起(:

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

Java具有服务提供商的概念,该概念是一种动态加载的方法(我敢肯定,如果您不符合您的需求,可以使用其他方法(。您可以在处理消息时迭代处理程序,并将每个处理程序传递给消息实例。每个处理程序都决定是否要处理消息。您甚至可以使handle返回boolean,以表明该链可以停止致电后续处理程序,如果您愿意。

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

不需要随着代码的修改而更改的switch,您只需重新配置jar的构建方式即可。这也是开放闭合原理的一个很好的例子,其中您的代码不更改但开放为扩展。

也许下面类似。它确实有一个开关,但是每种类型的代码都在枚举中。

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
    }
}

最新更新