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