【问题标题】:Best way to create a subclass object based on a command line argument基于命令行参数创建子类对象的最佳方法
【发布时间】:2014-03-08 20:12:57
【问题描述】:

我有几个扩展超类的子类,我想让命令行界面用户选择要使用的子类。所有子类都具有相同的构造函数形式。

例如,我希望能够调用run --subclass=Subclass1,导致调用Subclass obj = new Subclass(arg1, arg2)。我可以想到几种方法来做到这一点,但我认为这种模式经常出现,以至于有一种标准或公认的方法来做到这一点;如果没有,我想做最优雅和最简单的事情。

这是我目前的建议(假设有一个包含命令行参数的Namespace 对象):

SuperClass createObject(Namespace namespace, 
                        ArgumentClass1 arg1, 
                        ArgumentClass2 arg2) throws Exception {
    Map<String, Class<? extends SuperClass>> classMap =
        ImmutableMap.<String, Class<? extends SuperClass>>builder()
            .put("subclass1", SubClass1.class)
            .put("subclass2", SubClass2.class)
            .build();
    Constructor<? extends SuperClass> constructor =
        classMap.get(namespace.getString("subclass"))
            .getConstructor(ArgumentClass1.class, ArgumentClass2.class);
    return constructor.newInstance(arg1, arg2);
}

当子类构造函数都没有参数时,这可以通过不使用Constructor 并使用return classMap.get(namespace.get("subclass")).newInstance(); 来简化。请注意,一个缺点是这可能会引发需要在此处或上游处理的多个异常(InstantiationExceptionIllegalAccessExceptionNoSuchMethodExceptionInvocationTargetException)之一。

这合理吗?这是最好的方法吗?有标准模式可以使用吗?

【问题讨论】:

    标签: java oop inheritance factory abstract-factory


    【解决方案1】:

    我建议为每个子类创建一个工厂类,并将这些工厂的实例放入您的classMap。这将帮助您避免反射(并且可能在性能上更好)。

    SuperClass createObject(Namespace namespace, 
                            ArgumentClass1 arg1, 
                            ArgumentClass2 arg2) throws Exception {
        Map<String, SubClassFactory> classMap = ImmutableMap.<String, SubClassFactory>builder()
                .put("subclass1", new SubClassFactory1())
                .put("subclass2", new SubClassFactory2())
                .build();
        return classMap.get(namespace.getString("subclass")).newInstance(arg1, arg2);
    }
    

    PS:如果每个 java 运行时只需要一个实例,那么这些 SubClassFactory 也可以是枚举。

    【讨论】:

    • 除了性能之外还有其他原因可以避免反射吗?这需要更多的代码——每个子类都有一个完整的工厂类。
    • 反射往往会降低代码的可读性并阻碍 IDE 理解您的代码。您应该尽可能避免反思。 (但在您的具体情况下,所有这些论点并不真正匹配。如果您对使用反射有更好的感觉 - 那为什么不呢?!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 2013-01-22
    • 1970-01-01
    • 2013-01-20
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多