我正在读一个Stream,它提供了一个标识符(一个简单的int)。根据int的不同数据,我需要将其转化为对象。到目前为止,我为每个对象类型创建了类,每个类提供了一个read(InputStream输入)方法,该方法读取要为这种对象读取的任何数据(所有对象类都从公共基类继承)。 /> 但是,有许多id,因此有很多类。确定和创建类实例的最优雅方法是什么? 我首先尝试的最天真的方法是使用switch-case块来创建实例,但我发现它使代码混乱(不合理)。它还迫使我在编译时提供每个班级 第二个尝试是创建一个映射,将每个int映射到一个类,并使用newInstance()来创建对象。仍然存在我需要初始化地图的问题,这仍然要求我在编译时提供每个类。它或多或少只是将杂乱的地方从一个地方移到另一个地方 不需要删除编译时依赖项,如果可能的话,它只是一个奖励。主要目标是避免使用样板代码。
约束:我不想添加库来解决这个问题。我的反思很好。
答案 0 :(得分:5)
另一种方法是仍然使用Map但基本上使用后期绑定,如果这是更可取的。您甚至可以将配置存储在属性文件中,如:
1=java.lang.String
2=my.class.Something
...etc...
然后你做这样的事情:
Map<Integer,ObjectFactory> loader = ... // load from properties; fairly trivial
假设:
public class ObjectFactory {
private Final String className;
private transient Class clazz;
public ObjectFactory(String className) {
this.className = className;
}
public Object createInstance() {
try {
if (clazz == null) {
clazz = Class.forName(className);
}
return clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateExxception("Could not crate " + className, e);
}
}
}
答案 1 :(得分:1)
我认为你的地图解决方案听起来不错,但是将初始地图设置移出Java代码并转移到配置文件中。 (Class.forName将在这里提供帮助)
答案 2 :(得分:1)
您可以拥有原型的注册表。
您希望能够创建的每个类的原型(在某个时间点)可以在运行时添加到您的注册表对象中,这些原型每个都有自己唯一的整数ID。
当你想要一个id为x
的对象时,你只需要求你的注册表对象克隆并返回id为x
的原型。 (如果当前没有注册此类原型,则返回null。)
在内部,注册表可以是用于快速检索的(哈希)映射,但它可以很容易地成为原型列表(确保所有原型实现注册表可以使用的公共接口)。最好的是,不需要反思!