簡體   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