通过策略模式处理 Java 异常?

标签 java exception-handling

我煮了一个类ExceptionHandler<T extends Exception, OptionalReturnType> (见下文)以消除一些(我认为的)样板代码,这些代码使实际实现变得困惑,同时如果将来需要,仍然为显式异常处理提供一个钩子(Hook)。在大多数情况下,在我的应用程序(本质上是科学计算)中,没有从异常中恢复之类的东西——我需要记录问题以便修复它,否则我只会重新运行一次问题得到纠正。

其他人是否这样做(至少,在我的特定应用情况下)?这样做是否愚蠢(如果是,请解释一下为什么会很好)?

异常处理程序:

public abstract class ExceptionHandler<ExceptionType extends Exception,OptionalReturn> {
 public abstract OptionalReturn handle(ExceptionType e);

//assorted boilerplate ExceptionHandling, e.g.:

 public static <ET extends Exception> ExceptionHandler<ET, ?> swallower(final boolean printStackTrace, final String string) {
  return new ExceptionHandler<ET,Object>() {
   @Override public Object handle(ET e) {
    if(printStackTrace) { e.printStackTrace(); }
    if(string!=null && !string.isEmpty()) { System.err.println(string); }
    return null;
   }
  };
 }

 public static <ET extends Exception> ExceptionHandler<ET, ?> swallower() { return swallower(false,null); }

}

示例使用(我正在削减,所以我实际上并没有写太多):
public class Getter<From> implements Function<Future<? extends From>, From> {

private ExceptionHandler<InterruptedException,?> IEH;
private ExceptionHandler<ExecutionException,?> EEH;

public static final ExceptionHandler<InterruptedException,?> IEH_SWALLOWER = ExceptionHandler.swallower(true,"Returning null.");
public static final ExceptionHandler<ExecutionException,?> EEH_SWALLOWER = ExceptionHandler.swallower(true,"Returning null.");

private Getter() { this(IEH_SWALLOWER,EEH_SWALLOWER); }
private Getter(ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
    this.IEH = IEH;
    this.EEH = EEH;
}

public static <T> Getter<T> make() { return new Getter<T>(); }

public static <T> Getter<T> make(ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
    return new Getter<T>(IEH, EEH);
}

@Override public From apply(Future<? extends From> from) {
    if (from==null) throw new NullPointerException("Null argument in call with Getter.");
    return getter(from, IEH, EEH);
}

private static <T> T getter(Future<T> src, ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
    try { return src.get(); }
    catch (InterruptedException e) { IEH.handle(e); }
    catch (ExecutionException e) { EEH.handle(e); }
    return null;
    }

}

Guava 一起使用库来做一些令人尴尬的并行计算,并将 Futures 的实际 Iterable 转换为类似于 Iterables.transform(futureCollection,Getter.make()) 的东西而不是内部类和异常处理的纠结。

最佳答案

老实说,我发现代码很难遵循和理解。满是static这在 OO 设计中通常是一个不好的迹象,并且很难遵循泛型。

像这样更简单的东西不也可以吗?

private static <T> T getter(Future<T> src) {
    try { return src.get(); }
     catch (InterruptedException e) { handle( "some text"); }
     catch (ExecutionException e) { handle( e ) }
     return null;
    }

您可以实现尽可能多的 handle在基类(或静态实用程序类)中根据需要使用方法,并根据需要在 catch block 中使用它们。将根据签名选择方法,因此如果要打印文本,则传递字符串,如果要堆栈跟踪,则传递异常(或两者都传递)。这导致组合:
handle( String msg )
handle( Exception e )
handle( Exception e, String msg )

此解决方案具有较少的 if ,这通常也是一个好兆头。

但是我可能错过了一点,因为您发布的代码只是整个代码的摘录。

看看这个问题,这也是相关的:Pluggable Error Handling Strategy

编辑

如果我上面提出的解决方案对您的需要来说太简单了,这里有另外两种方法:
public class AbstractGetter<From> implements Function<Future<? extends From>, From> {

private abstract handleInterrupt( Exception e );
private abstract handleExecution( Exception e );

private static <T> T getter(Future<T> src ) {
    try { return src.get(); }
    catch (InterruptedException e) { handleInterrupt(e) }
    catch (ExecutionException e) { handleExecution(e) }
    return null;
    }
}

并且您实现了对应于各种异常处理策略的 X 具体类。本质上就是 template图案。

您仍然可以使用委托(delegate),但在更粗粒度的级别上。您无需提供单独的处理程序,而是提供处理程序策略。这是strategy 的一种变体。那么图案。
  public interface ErrorStrategy
  {
        public void handleInterrupt(Exception e);
        public void handleExecution(Exception e);
  }

  public class Getter<From> implements Function<Future<? extends From>, From> {

  ErrorStrategy handler = new DefaultErrorStrategy(). // default one

  public Getter<From>()
  {
  }

  public Getter<From>( ErrorStrategy h )
  {
      this.handler = h.
  }

  private static <T> T getter(Future<T> src ) {
    try { return src.get(); }
    catch (InterruptedException e) { handler.handleInterrupt(e) }
    catch (ExecutionException e) { handler.handleExecution(e) }
    return null;
    }
 }

您可以创建所需的 X 错误处理策略。

关于通过策略模式处理 Java 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2254266/

相关文章:

syntax - 为什么我们需要异常处理?

php - 处理 php 页面错误的最佳方法?

java - Clojure 中的定时素数生成

java - CPU 资源和时钟周期 : System. out.println 或递增标志

java - AES用openssl命令行工具加密,用Java解密

java - 如何在 DynamoDbEnhancedClient 中动态更改表名(Aws Sdk V2 for Java)

.net - ELMAH与企业库异常处理 block

java - @ExceptionHandler(Exception.class) 不处理所有类型的异常

language-agnostic - 如何编写安全代码 : Condition checking Vs Exception handling?

java - 批量插入时如何选择正确的批量大小