【问题标题】:Specify which implementation of Java interface to use in command line argument在命令行参数中指定要使用的 Java 接口实现
【发布时间】:2014-06-06 02:01:48
【问题描述】:

假设我有一个 Java 接口 Blender.java 和各种实现 Cuisinart.javaOster.javaBlendtec.java 等。现在我想写一个这样的程序:

public class Blendifier {
    // ...
    public static void main(String... args) {
        Blender blender = new Cuisinart();
        blender.blend();
    }
}

但是现在如果我想使用Blendtec而不是Cuisinart,我必须打开源代码,更改代码,然后重新编译。

相反,我希望能够在运行程序时指定使用哪个Blender,方法是将我想要的类名写为命令行参数。

但是如何从包含类的 name 的字符串转到构造该类的实际 instance 呢?

【问题讨论】:

  • Reflection。或者您可以使用 DI 框架,例如 Spring 或 Guice。
  • 反思是一个巨大的话题,我对此一无所知 - 如果有人能让我更接近如何使用它来解决这个特殊问题,我会很高兴......
  • 我现在没有时间写一个完整的答案,但我一直使用反射的方式来做这件事。我的“AuthorizationService”采用.properties 配置文件将权限名称映射到实现类;我的“HtmlRenderer”在配置的包中查看是否有一个类 <Something>Renderer 用于在输入中找到的任何标签,例如<pre> 在输入中找到,它在实例化“HtmlRenderer”时在给定的包中查找类PreRenderer。添加新品牌的搅拌机时,无需修改代码以添加新的caseif

标签: java interface command-line-arguments classname


【解决方案1】:

您有几种方法可以做到这一点:

例如if-else 构造

Blender blender = null;
if (args[0].equals("Cuisinart")) {
   blender = new Cuisinart();
} else if (...)

其中 args[0] 是您的第一个命令行参数。

【讨论】:

    【解决方案2】:

    如果您不想遇到 Java 反射的麻烦,您可以编写一个简单的静态工厂方法,该方法接受一个字符串并返回相应的对象。

    public static Blender createBlender(String type){
        switch(type){
        case "Cuisinart": return new Cuisinart();
        case "Oster": return new Oster();
        //etc
        }
    }
    

    然后你只需将你的命令行参数传入它,你就会拥有你需要的任何 Blender。

    唯一可能的设计问题是您必须为每个实现 Blender 的类键入一行,因此如果您稍后添加更多类型,则必须更新该方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 2020-09-10
      相关资源
      最近更新 更多