我的代码看起来像这样:
if(num == 1) {
return new Alg1();
} else if (num == 2) {
return new Alg2();
}
...
else if (num == n) {
return new AlgN();
}
我曾尝试使用策略模式,但似乎它不能满足减少if语句的任务,请你建议我做其他方法,谢谢
答案 0 :(得分:6)
您可以使用反射
try {
return Class.forName("mypackage.Alg" + num).newInstance();
} catch (Exception e) {
// handle exception
}
您可以选择使用RuntimeException进行换行,或者如果它是您期望的那样,则可以将其换行
public static Algorythm loadAlgo(int n) throws IOException {
try {
return Class.forName("mypackage.Alg" + num).newInstance();
} catch (Exception e) {
if (e instanceof IOException)
throw (IOException) e;
throw new IOException("Unable to load Algo", e);
}
您必须使用此newInstance()
方法捕获所有异常,而不仅仅是已检查的异常,因为它不会包含构造函数中抛出的异常。你可以使用更长的
try {
return Class.forName("mypackage.Alg" + num).getConstructor().newInstance();
} catch (Exception e) {
// handle exception
}
然而,在这种情况下它没有太大区别,除非抛出的异常将被包装,你可能需要打开它们才能看到它们。
答案 1 :(得分:6)
除非您要提供40亿个Alg*
课程,否则请使用enum
代替int
:
enum Strategy {
ALG_1 { @Override public Alg1 newInstance() { return new Alg1(); },
ALG_2 { @Override public Alg2 newInstance() { return new Alg2(); },
// ...
;
public abstract AlgBase newInstance();
}
然后不需要任何条件:
return strategy.newInstance();
其中strategy
是Strategy
的实例。
答案 2 :(得分:3)
如果要动态添加新算法,可能需要查看spi。 https://docs.oracle.com/javase/tutorial/ext/basics/spi.html。这些方法意味着所有算法都必须是初始化的,如果一个算法失败,那么任何算法都是可用的。
使用文本文件,您可以注册接口的实现并通过以下方式解决这些实现:
ServiceLoader<Algorithm> algorithms = ServiceLoader.load(Algorithm.class);
for (Algorithm algorithm : algorithms) {
if (algorithm.getId().equals(num)) {
return algorithm;
}
}
throw new IllegalArgumentException("Algorithm with num " + num + " does not exist");
这将为该算法的所有实现返回Iterable。你可以遍历它们以找到正确的。
如果您在一次运行应用程序时经常解析算法,则可能需要将算法存储/缓存在Map中。
如果您不想使用spi,也可以手动创建此地图。
private static final Map<Integer, Algorithm> ALGORITHMS;
static {
Map<Integer, Algorithm> algs = new HashMap<>();
algs.put(1, new Alg1());
algs.put(2, new Alg2());
algs.put(3, new Alg3());
ALGORITHMS = Collections.unmodifiableMap(algs);
}