gpt4 book ai didi

java - 创建对象时处理二维条件的方法?

转载 作者:行者123 更新时间:2023-11-29 07:34:37 26 4
gpt4 key购买 nike

我有两个变量,foobar,它们决定了我需要创建哪种对象。目前,这两个都可以包含两个不同的值,并且对象是这样创建的:

Result createResult(int foo, int bar) {
if(foo == 0) {
if(bar == 0) return new FirstResult();
if(bar == 1) return new SecondResult();
}else if(foo == 1) {
if(bar == 0) return new ThirdResult();
if(bar == 1) return new FourthResult();
}
return null;
}

// Common interface for all the objects
interface Result {

}

这只适用于这四种类型,但如果有更多类型怎么办?应该如何处理对象创建,以便更有效?

最佳答案

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
}

正如上面评论中已经提到的,您绝对需要实现hashCodeequals。如果您没有实现 equalshashCode,它将无法工作,因为如果键不相同(即使相等),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();
}
}

重点是您所有的构造函数(构造函数的委派者)现在都保存在 map factories 中。一旦达到某个临界大小,查找 factories.get(new CreationParams(foo, bar)) 将比许多 if 语句更快,因为它不需要迭代所有可能的目标对象,但是只有那些具有冲突哈希的。然后你可以立即调用 get 或者在现实世界中你可能想要检查 null 并在这种情况下抛出某种异常。

没有 Java 8

如果您卡在较旧的 Java 版本上,基本上有两种可能的解决方法。在这两种情况下,您都需要像这样创建自己的 Supplier 接口(interface)(从技术上讲,您不需要反射变体的接口(interface),因为它只需要一个您也可以直接使用的实现类):

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);
}
}
}

现在您可以按如下方式向 Map 添加类:

result.put(new CreationParams(0, 0), new ReflectionSupplier(FirstResult.class));

另一种选择是为每个实例只使用(匿名)类。优点是有一堆可以在编译时发现的错误(例如没有可用的默认构造函数)。缺点是这会产生大量的行。只需像这样添加到您的 map :

result.put(new CreationParams(0, 0), new Supplier() {
@Override
public Result get() {
return new FirstResult();
}
});

关于java - 创建对象时处理二维条件的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37519963/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com