代码之家  ›  专栏  ›  技术社区  ›  Carl

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

  •  2
  • Carl  · 技术社区  · 15 年前

    我准备了一节课 ExceptionHandler<T extends Exception, OptionalReturnType> (请参见下文)以消除一些(我认为是)样板代码,这些代码使实际实现变得混乱,同时如果将来需要,仍然提供一个用于显式异常处理的钩子。在大多数情况下,在我的应用程序中(基本上是一个科学计算),没有从异常中恢复这样的事情-我需要一个问题日志,这样我就可以修复它,否则我只会在问题被纠正后重新运行。

    异常处理程序:

    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 库来进行一些令人尴尬的并行计算,并将未来的实际Iterable转换为 Iterables.transform(futureCollection,Getter.make())

    2 回复  |  直到 15 年前
        1
  •  2
  •   Community CDub    8 年前

    我发现代码很难理解。它充满了 static

    像这样简单的东西也行吗?

    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块中使用它们。方法将根据签名进行选择,因此如果要打印文本,则传递字符串,如果要堆栈跟踪,则传递异常(或两者都传递)。这导致了以下组合:

    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 图案。

    您仍然可以使用委托,但是在更粗粒度的级别上。不是提供单个处理程序,而是提供处理程序策略。这是一种 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错误处理策略。

        2
  •  2
  •   GreenieMeanie    15 年前

    我认为这是一个很好的解决方案,但它可以受益于ExceptionHandlerFactory和一些xml文件。