Java 替换if-else语句

Java 替换if-else语句,java,algorithm,design-patterns,Java,Algorithm,Design Patterns,我有一个类似这样的代码: if(num == 1) { return new Alg1(); } else if (num == 2) { return new Alg2(); } ... else if (num == n) { return new AlgN(); } 我尝试过使用策略模式,但似乎它不能满足减少if语句的任务,请您建议我其他方法,谢谢您可以使用反射 try { return Class.forName("mypackage.Alg" + num).newInstan

我有一个类似这样的代码:

if(num == 1) {
return new Alg1();
} else if (num == 2) {
return new Alg2();
}
...
else if (num == n) {
return new AlgN();
}
我尝试过使用策略模式,但似乎它不能满足减少if语句的任务,请您建议我其他方法,谢谢您可以使用反射

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
}

但是,在这种情况下,它没有多大区别,除非抛出的异常将被包装,并且您可能必须将其打开才能看到原始异常。

除非您打算提供40亿
Alg*
类,否则请使用
枚举而不是
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

的实例。如果您想动态添加新算法,您可能需要查看spi。这些方法意味着所有算法都必须是可初始化的,如果一个算法不能构造,那么没有一个算法是可用的

使用文本文件,您可以注册接口的实现,并通过以下方式解析这些实现:

    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");
ServiceLoader algorithms=ServiceLoader.load(Algorithm.class);
用于(算法:算法){
if(algorithm.getId().equals(num)){
返回算法;
}
}
抛出新的IllegalArgumentException(“具有num“+num+”的算法不存在”);
这将为该算法的所有实现返回一个Iterable。你可以通过循环找到正确的一个

如果经常在应用程序的一次运行中解析算法,则可能需要在映射中存储/缓存算法

如果不想使用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);
}
私有静态最终映射算法;
静止的{
Map algs=新的HashMap();
algs.put(1,新的Alg1());
algs.put(2,新的Alg2());
algs.put(3,新的Alg3());
算法=集合。不可修改映射(algs);
}

使用开关。。。案例:不要使用Class.newInstance()而是使用Class.getConstructor().newInstance()(Class.newInstance()没有sane异常方案)。典型的过度使用反射。@k5_u我没有提到异常处理应该如何工作,我将把它添加到我的答案中。你真的认为异常处理应该是这样的吗?@k5_u我很乐意为你提供一个完整的替代答案,即不是一个带“…”的答案我会让你在这里填写所有重复的代码。@k5\我欢迎一个更干净、更简单的建议。一个好建议。如果服务抛出异常,您可以介绍如何处理异常吗+1对于不需要的算法,类初始化时会抛出异常。你会怎么处理呢?“你真的认为异常处理应该是这样的”-也就是说,我想假装它们从未发生过。我为serviceloader添加了一些错误处理。很明显,快速失败,尽早失败并不是一种糟糕的策略。为了澄清这一点,我在最初的回答中添加了一条评论。