繁体   English   中英

将异常作为方法参数处理

[英]Handling an exception as a method argument

我正在寻找一种设计模式来处理作为方法参数接收的Exception实例。

为了解决这个问题,我正在使用GWT并具有各种异步处理程序,这些处理程序通常以类似于以下形式的形式出现:

public interface AsyncCallback<T> {

  void onFailure(Throwable caught);

  void onSuccess(T result);

}

因此, onFailure方法接收我需要处理的Throwable实例。

现在,例如,在此方法中我可以收到许多例外

  • ConstraintViolationException
  • TimeoutException
  • NoSuchElementException

在我的处理代码中,我当然可以编写以下内容:

void handleException(final Exception e) {
    if(e instanceof TimeoutException) {
        handleTimeout();
    } else if (e instanceof NoSuchElementException) {
        handleInvalidElement();
    } else {
        stopAndCatchFire();
    }
}

但是在我看来,这看起来非常丑陋。 大型if..else if链与大量使用instanceof相结合似乎是应该避免的事情。

我认为也许我可以使用try...catch构造来处理类似于以下内容的Exception

void handleException(final Exception e) {
    try {
        throw e;
    } catch (TimeoutException te) {
        handleTimeout();
    } catch (NoSuchElementException nsee) {
        handleInvalidElement();
    } catch (Exception ex) {
        stopAndCatchFire();
    }
}

但这似乎是一种滥用。 您是否看到第二种方法或我可以避免第一种情况的另一种方法的不利之处?

您是否不能拥有一个由它们处理的异常类型作为关键字的exceptionHandlers字典,那么当您获得异常时,您会在字典中查找该异常类型的处理程序。 如果存在,则将异常传递给处理程序,如果不存在,则使用默认处理程序。

因此,您的处理程序将变成这样:

void handleException(final Exception e) {
    if (handlers.containsKey(e.getType())
    {
        handlers[e.getType()].handle(e);
    }
    else
    {
         defaultHandler.handle(e);
    }
}

我的Java有点生锈,因此该示例是c-sharpy,但应该足够简单以进行翻译(尽管我记得不要大写所有内容的首字母:))

这种方法应具有的优点是您可以简单地添加新的处理程序。

但是,如果您具有相同的子类型处理程序,则将受到影响,因为您将必须显式注册每个子类型。

要解决此问题,只需让每个处理程序负责决定是否可以处理异常:

public interface ExceptionHandler
{
     bool canHandle(Exception e);
     void handle(Exception e)
}

然后只需将处理程序放在一个列表中,就可以迭代地询问每个处理程序是否可以处理当前异常,当找到一个可以处理的异常时,请使其进行处理。

但是在我看来,这看起来非常丑陋。 大型if..else if链与大量使用instanceof相结合似乎是应该避免的事情。

我不同意 我认为这段代码正好使用两种语言的构造。 如果代码变得难以管理(子句过多),则应该质疑一般的错误处理方法,而不是此方法的细节。 在那个阶段,您可能要考虑AOP。

另一方面,第二种方法太可怕了;)

您可以通过处理函数内部异常中的if语句来使其更加优雅。

void handleException(Exception e){
    handleOne(e)
    handleTwo(e)
    ...
}

看起来更漂亮。 当然,每个函数总是被调用,但是它的第一行只是一个if语句。 有一些变化-例如,使您的句柄函数番石榴函数对象,将它们放入列表中,并对其进行迭代,直到获得第一个返回“ true”的对象。 就像是:

public class handlerOne implements Function<Exception, Boolean> {

    Boolean apply(Exception input) {        
        return handlerOne();
    }
}

然后,您的handle函数可能类似于:

void handleException(Exception e){
    list<Function<Exception, Boolean> list = Object.getHandlers(); //store your handlers somewhere
    for(Function<Exception, Boolean> f : list){
        if(f.apply(e)){
            break
        }
    }
}

这样,您可以确保仅调用一个有效的处理程序,并且可以通过更改列表的顺序来控制顺序,因为列表迭代器将按顺序返回它们。

应该避免针对异常的控制流,并且绝对不应将其置于onFailure中。 onFailure方法应尽可能简单。

修改异步运行的任何代码以处理那里的异常情况。 可以通过在执行任何操作之前检查元素是否存在来处理ElementNotFound-exception。 可以通过try .. catch块将可以超时的代码(调用Web服务或其他东西)包围起来来处理超时异常。 然后扩展结果类型T,以包含发生超时或找不到元素的额外信息(如果需要)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM