在运行时动态选择类

时间:2011-02-23 10:37:03

标签: java java-ee class-design classloader

我试图想出一个解决方案,根据消息类型在运行时选择处理“消息”的类。 我知道我可以使用这样的东西

if msg_type = "A"
  MsgAProcessor.execute(message);
else if msg_type = "B"
  MsgBProcessoror = execute(message);
....
....
....

我不想使用上面的方法,因为我不希望代码知道我可以处理的消息类型的任何信息。我希望将来能够为新的消息类型添加新的消息处理器。我现在想到的解决方案如下

目前有3个消息处理器

MsgAProcessor
MsgBProcessor
MsgBProcessor

所有三个类都有一个名为execute的方法,它将以自己的方式处理消息。我创建了一个名为MsgProcessor的接口,并在接口中添加了execute()方法。

现在我很难知道调用者应该调用哪个消息处理器而不必检查消息类型。例如,我不能这样做

MsgProcessor proc = new MsgAprocessor() proc.execute()

上述内容将被要求在if语句中,因为它需要在找到消息类型后立即调用。我还想避免使用实现类类型进行实例化。

有没有更好的方法来实现同样的目标?

我希望能够从接口调用MsgProcessor.execute,并让运行时环境知道要根据消息类型调用哪个实现类。

3 个答案:

答案 0 :(得分:5)

  1. 让接口处理器具有方法execute()。你的三个MsgProcessors都实现了这一点。
  2. 有一个单独的 ProcessorControl 类,其中包含提交(字符串消息)方法。每当有新消息出现时,您只需执行 ProcessorControl.submit(消息)
  3. 现在,ProcessorControl有一个方法addProcessor(Proccesor proc,String type),它将处理器添加到以类型为键的哈希表中。因此,现在为每个处理器分配了一个类型。
  4. 在提交方法中,只需获取 hashtable.get(type).execute(proc)
  5. 这是一个简单的命令模式。

答案 1 :(得分:1)

您可以使用Map从消息类型映射到消息处理器。要解耦实现,您可以使用ServiceLoader: http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html

答案 2 :(得分:1)

您希望使用动态类加载:Class.forName(THE CLASS NAME)

您的命令可以包含完全限定的类名,也可以使用属性文件或命名约定映射到它。您的命令的所有实现都应该实现接口(就像您已经做过的那样)。从中接收命令get class name,然后创建命令实例并调用其execute方法:

((Processor)Class.forName(className).newInstance()).execute()