我有几个扩展超类的子类,我想让命令行界面用户选择要使用的子类。所有子类都具有相同的构造函数形式。
例如,我希望能够致电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();
来简化这一点。请注意,一个缺点是,这可能会导致需要在此处或上游处理的若干异常(InstantiationException
,IllegalAccessException
,NoSuchMethodException
,InvocationTargetException
)之一。
这合理吗?这是最好的方式吗?是否有标准模式可供使用?
答案 0 :(得分: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运行时只需要一个实例,那么这些SubClassFactorys可以是枚举。