if/else模式应该是非常有效的一个相当大的尺寸。但是,如果事情变得非常巨大,这种变化和可读性受损。我建议使用正确构造函数的HashMap-Lookup来加快结果确定。这需要你创建可用于在HashMap
的关键类:
class CreationParams {
private final int foo;
private final int bar;
CreationParams(final int foo, final int bar) {
this.foo = foo;
this.bar = bar;
}
// make sure to implement hashCode & equals so this class can be efficiently used in a Map
}
正如已经在评论中提及上面,你绝对需要实现hashCode
和equals
。如果你没有实现equals
或hashCode
它不会工作,因为如果密钥不相同(即使相等),hashmap查找也会失败。
现在,您可以轻松地将参数组合映射到构造函数并查找结果。考虑下面这个例子:
class ResultFactory {
private static final Map<CreationParams, Supplier<Result>> factories = createFactoryMap();
private static Map<CreationParams, Supplier<Result>> createFactoryMap() {
final Map<CreationParams, Supplier<Result>> result = new HashMap<>();
result.put(new CreationParams(0, 0), FirstResult::new);
result.put(new CreationParams(0, 1), SecondResult::new);
// ...
return result;
}
Result createResult(int foo, int bar) {
return factories.get(new CreationParams(foo, bar)).get();
}
}
的一点是,所有构造函数(以及委托者的构造函数)现在保存在地图factories
。查找factories.get(new CreationParams(foo, bar))
一旦达到一定的临界值就会比if语句快很多,因为它不需要迭代所有可能的目标对象,而只需要迭代具有冲突散列的目标对象。然后,您可以立即致电get
或在现实世界中,您可能希望检查null,并在此之前抛出某种异常。
不带Java 8
如果你是停留在一个旧的Java版本,你基本上有两种可能的解决方法。在这两种情况下,您都需要像这样创建您自己的供应商界面(从技术上讲,您不需要用于反射变体的界面,因为它只需要一个也可以直接使用的实施类):
interface Supplier {
Result get();
}
,其中一个方法是使用反射它需要较少的源代码:
class ReflectionSupplier implements Supplier {
final Class<? extends Result> clazz;
ReflectionSupplier(final Class<? extends Result> clazz) {
this.clazz = clazz;
}
public Result get() {
try {
return clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new Error(e);
}
}
}
现在你可以添加如下类地图:
result.put(new CreationParams(0, 0), new ReflectionSupplier(FirstResult.class));
其他另一种方法是只为每个实例使用(匿名)类。好处是可以编译时发现一堆错误(比如没有默认构造函数)。缺点是这会产生大量的线。只需添加到您的地图是这样的:
result.put(new CreationParams(0, 0), new Supplier() {
@Override
public Result get() {
return new FirstResult();
}
});
我会建议一个'enum'和switch-case。 –
你所描述的是工厂模式的用例。 –
你可以更具体一点关于你的用例吗?解决方案取决于你想要达到的目标。 – Hugo