2012-04-16 72 views
29

我已經閱讀了很多關於代碼重構和避免if else語句的主題。 其實,我有一個課,我使用了很多if - else條件。如何避免很多其他條件

更多細節:我使用的是拉解析器和我SOAP響應的每一行,我會檢查是否有標籤我感興趣的,如果沒有,檢查另一個標記等:

if(eventType == XmlPullParser.START_TAG) { 
      soapResponse= xpp.getName().toString(); 

      if (soapResponse.equals("EditorialOffice")){ 
       eventType = xpp.next(); 
       if (xpp.getText()!=null){ 
       editorialOffice += xpp.getText(); 
       } 
      } 
      else if (soapResponse.equals("EditorialBoard")){ 
       eventType = xpp.next(); 
       if (xpp.getText()!=null){ 
       editorialBoard += xpp.getText(); 
       } 
      } 
      else if (soapResponse.equals("AdvisoryBoard")){ 
       eventType = xpp.next(); 
       if (xpp.getText()!=null){ 
       advisoryBoard += xpp.getText(); 
       } 
      } 
     } 
     eventType = xpp.next(); 
    } 

現在,我想用其他的,而不是那些如果其他條件,但我不知道是什麼。

你可以給我一個例子或一個很好的教程頁嗎?

謝謝。

+0

你可以維護字符串到程序中其他地方的枚舉映射,從映射中抽出與返回字符串關聯的枚舉(如果字符串不在映射中,則使用默認的'NO_MATCH')並寫入在枚舉上切換語句。它可能會使代碼更清晰,但會增加額外的間接層。你必須判斷這是否值得。 – 2012-04-16 14:24:42

+2

檢查: http://stackoverflow.com/questions/519422/what-is-the-best-way-to-replace-or-substitute-if-else-if-else-trees-在程序中 希望對您有所幫助 – 2012-04-16 14:27:54

+0

請注意,出於性能方面的原因,您應該使用StringBuilder而不是+ =來連接字符串。 – 2012-04-19 14:40:19

回答

18

在這個特定的情況下,由於碼是所有3的情況下,除了字符串基本上相同被附加到,我將不得不爲每個字符串的映射條目正在構建:

Map<String,String> map = new HashMap<String,String>(); 
map.put("EditorialOffice",""); 
map.put("EditorialBoard",""); 
map.put("AdvisoryBoard",""); 
// could make constants for above Strings, or even an enum 

,然後將您的代碼更改爲以下內容

if(eventType == XmlPullParser.START_TAG) { 
    soapResponse= xpp.getName().toString(); 
    String current = map.get(soapResponse); 
    if (current != null) { 
     eventType = xpp.next(); 
     if (xpp.getText()!=null){ 
      map.put(soapResponse, current += xpp.getText()); 
     } 
    } 
    eventType = xpp.next(); 
} 

否「if ... then ... else」。甚至沒有爲戰略模式增加多個類的複雜性等。地圖是你的朋友。在某些情況下策略很棒,但是這個策略非常簡單,無需解決。

5

除了zzzzzzz(etc。)的評論......請記住,您正在使用XmlPullParser,它使您可以編寫您喜歡的代碼。你可以註冊一些回調來分割你的代碼並使其更好,但如果可能的話,只需使用SimpleXML庫或類似的代碼。

此外,你可以重構你的代碼,使其更具可讀性和更少的冗長。例如,爲什麼你在每個if語句中調用xpp.next()?爲什麼不只在外面調用它:

if(eventType == XmlPullParser.START_TAG) { 
    soapResponse= xpp.getName().toString(); 
    if (soapResponse.equals("EditorialOffice") && xpp.getText()!=null){ 
     editorialOffice += xpp.getText(); 
    } 
    else if (soapResponse.equals("EditorialBoard") && xpp.getText()!=null){ 
     editorialBoard += xpp.getText(); 
    } 
    else if (soapResponse.equals("AdvisoryBoard") && xpp.getText()!=null){ 
     advisoryBoard += xpp.getText(); 
    } 
} 
eventType = xpp.next(); 
+0

謝謝@Cristian,事實上,我正在從服務器獲取xml響應,我不知道我是否可以使用別的東西,這與XML pull解析器非常相似。我在每條語句上調用xpp.next(),而當找到我要查找的開始標記時,則在下一行中,我會找到需要的變量,並將其放入我的局部變量中。 – 2012-04-16 14:24:58

+0

['XmlPullParser.getName()'](http://www.xmlpull.org/v1/doc/api/org/xmlpull/v1/XmlPullParser.html#getName())返回'String',所以有不需要調用'.toString()'。 – 2012-04-16 14:41:22

+0

@Ana只是看看SimpleXML庫;它會讓你的生活更輕鬆,更快樂。 – Cristian 2012-04-16 15:12:48

6

在Java 7中,您可以在字符串上進行切換。你可以使用它,如果你可以使用它;-)

+12

+1「如果你可以使用它,你可以使用它。如果我們有雞蛋,我們可以有火腿和雞蛋,如果我們有火腿。 – 2012-04-16 15:03:05

33

試着看看戰略模式。

  • 做一個接口類用於處理響應(IMyResponse)
    • 使用此IMyResponse創建AdvisoryBoardResponse,EditorialBoardResponse類
  • 創建與soapresponse值爲鍵,你的戰略,作爲一個詞典值
  • 然後,您可以使用IMyResponse類的方法從字典中獲取它

小例子:

// Interface 
public interface IResponseHandler { 
    public void handleResponse(XmlPullParser xxp); 

} 

// Concrete class for EditorialOffice response 
private class EditorialOfficeHandler implements IResponseHandler { 
    public void handleResponse(XmlPullParser xxp) { 
     // Do something to handle Editorial Office response 
    } 
} 

// Concrete class for EditorialBoard response 
private class EditorialBoardHandler implements IResponseHandler { 
    public void handleResponse(XmlPullParser xxp) { 
     // Do something to handle Editorial Board response 
    } 
} 

在您需要創建的處理程序的地方:

Map<String, IResponseHandler> strategyHandlers = new HashMap<String,IResponseHandler>(); 
strategyHandlers.put("EditorialOffice", new EditorialOfficeHandler()); 
strategyHandlers.put("EditorialBoard", new EditorialBoardHandler()); 

如果您收到響應:

IResponseHandler responseHandler = strategyHandlers.get(soapResponse); 
responseHandler.handleResponse(xxp); 
+0

謝謝@hwcverwe,這在我看來是一個好主意。你能否給我一個更精確的例子來說明如何做到這一點?非常感謝。 – 2012-04-16 14:27:31

+2

也許這適用於更復雜的多條件決策。但是這對於這種特殊情況來說不覺得太重了嗎?哎呀,我甚至更喜歡「如果,那麼,如果」通過這個解決方案,在這種特殊情況下(儘管存在其他更簡單的解決方案)。 – 2012-04-16 14:47:01

+0

@KevinWelker這有點複雜,但如果你考慮可維護性,將來會更容易。與其他響應處理程序一起擴展策略非常容易。而且它更易讀if-elseif-else語句 – hwcverwe 2012-04-16 14:59:28

3

你可以創建一個對ResponseHandler接口三個實現,一個用於if/else構造的每個分支。

然後有一個映射將不同的soapResponses映射到一個處理程序,或者是一個包含所有處理程序的列表(如果它可以處理該soapResponse)。

您還應該能夠將一些樣板代碼移動到響應處理程序類的常見可能抽象實現。

由於經常有這樣的許多變化。通過利用代碼重複一個實際上只需要一個實現:

class ResponseHandler{ 
    String stringToBuild = "" // or what ever you need 
    private final String matchString 

    ResponseHandler(String aMatchString){ 
     matchString = aMatchString 
    } 
    void handle(XppsType xpp){ 
     if (xpp.getName().toString().equals(matchString){ 
      eventType = xpp.next(); 
      if (xpp.getText()!=null){ 
       editorialOffice += xpp.getText(); 
      } 
     } 
    } 
} 

你的代碼變得

List<ResponseHandler> handlers = Arrays.asList(
    new ResponseHandler("EditorialOffice"), 
    new ResponseHandler("EditorialBoard"), 
    new ResponseHandler("AdvisoryBoard")); 
if(eventType == XmlPullParser.START_TAG) { 
    for(ResponseHandler h : handlers) 
     h.handle(xpp); 
} 
+0

謝謝@Jean Sxhauder,請給我一個如何使用它的例子嗎? – 2012-04-16 14:43:00

+0

增加了一個示例實現 – 2012-04-16 14:57:15

3

廣大疑問,這是一個並沒有真正的答案。 (我不使用肥皂經常)

這裏只是一些想法基於代碼:

首先,你可以獅重複的代碼

if (soapResponse.equals("EditorialOffice") 
||soapResponse.equals("EditorialBoard") 
||soapResponse.equals("AdvisoryBoard")){ 

你可以做的另一個好處是發揮周圍的開關staments像:

switch(soapResponse){ 
case "EditorialOffice": 
case "EditorialBoard": 
case "AdvisoryBoard": 
eventType = xpp.next(); 
       if (xpp.getText()!=null){ 
       advisoryBoard += xpp.getText(); 
       } 
break; 

你也應該考慮打破你考到小功能:

public bool interestingTag(string s){ 
return (soapResponse.equals("EditorialOffice") 
    ||soapResponse.equals("EditorialBoard") 
    ||soapResponse.equals("AdvisoryBoard")); 
} 

    public processData(xpp){ 
    eventType = xpp.next(); 
        if (xpp.getText()!=null){ 
        editorialBoard += xpp.getText(); 
        } 
    ....} 

這樣你可以處理所有的答案在一個while循環,你超長的if else變成5〜10線功能

但正如我說,有做同樣的事情這麼多的好方法

4

你還沒有提到,如果你可以或使用Java 7.從那個Java版本,你可以使用Strings in switch statements

除此之外,封裝邏輯每種情況下是一個好主意,例如:

Map<String, Department> strategyMap = new HashMap<String, Department>(); 
strategyMap.put("EditorialOffice", new EditorialOfficeDepartment()); 
strategyMap.put("EditorialBoard", new EditorialBoardDepartment()); 
strategyMap.put("AdvisoryBoard", new AdvisoryBoardDepartment()); 

然後,你可以簡單地從地圖上選擇了正確的策略,並使用它:

String soapResponse = xpp.getName(); 
Department department = strategyMap.get(soapResponse); 
department.addText(xpp.getText()); 

Department當然是在接口...

+0

經過所有工作中斷後,我終於提交了答案,但@ hwcverwe同時已經提交了幾乎相同的答案(參見上文)。 – 2012-04-16 15:29:22

0

你可以定義一個枚舉如下:

public enum SoapResponseType { 
    EditorialOffice(1, "description here") { 
     public void handle(XmlPullParser xpp) { 
      //do something you want here 
      return null; 
     } 
    }, 
    EditorialBoard(2, "description here") { 
     public void handle(XmlPullParser xpp) { 
      //do something you want here 
      return null; 
     } 
    }, 
    AdvisoryBoard(3, "description here") { 
     public void handle(XmlPullParser xpp) { 
      //do something you want here 
      return null; 
     } 
    }; 

    public static SoapResponseType nameOf(String name) { 
     for (SoapResponseType type : values()) { 
      if (type.getName().equalsIgnoreCase(name)) { 
       return type; 
      } 
     } 
     return null; 
    } 

    public void handle(XmlPullParser xpp) { 
     return null; 
    } 
} 

使用上述枚舉這樣的:

SoapResponseType type = SoapResponseType.nameOf("input string"); 
if (type != null) { 
    type.handle(xpp); 
} 

它是乾淨的代碼,是不是!