2017-05-27 61 views
0

因此,我想這個狀態機(在下一個代碼中有些狀態由於它們還沒有完成而丟失)與很多幾乎完全相同的狀態。 我確定有一個更好的方法來實現這個目標,但是我找不到它(可能有課,但我不確定)。改善狀態機

switch(firstState) { 
    case INITIAL: 
     if(c == 'g') { 
      builder.append(c); 
      firstState = FirstParserState.METHOD_G; 
     } 
     else if(c == 'p') { 
      builder.append(c); 
      firstState = FirstParserState.METHOD_P; 
     } 
     else 
      firstState = FirstParserState.ERROR; 

     break; 
    case METHOD_G: 
     if(c == 'e') { 
      builder.append(c); 
      firstState = FirstParserState.METHOD_E; 
     } 
     else 
      firstState = FirstParserState.ERROR; 

     break; 
    case METHOD_E: 
     if(c == 't') { 
      builder.append(c); 
      firstState = FirstParserState.METHOD_T; 
     } 
     else 
      firstState = FirstParserState.ERROR; 

     break; 
    case METHOD_T: 
     if(c == ' ') { 
      method = builder.toString(); 
      builder.setLength(0); 
      firstState = FirstParserState.WHISE_SPACE; 
     } 
     else 
      firstState = FirstParserState.ERROR; 

     break; 
    case METHOD_P: 
     if(c == 'o') { 
      builder.append(c); 
      firstState = FirstParserState.METHOD_O; 
     } 
     else 
      firstState = FirstParserState.ERROR; 

     break; 
    case METHOD_O: 
     if(c == 's') { 
      builder.append(c); 
      firstState = FirstParserState.METHOD_S; 
     } 
     else 
      firstState = FirstParserState.ERROR; 

     break; 
    case METHOD_S: 
     if(c == 't') { 
      builder.append(c); 
      firstState = FirstParserState.METHOD_T; 
     } 
     else 
      firstState = FirstParserState.ERROR; 

     break; 
    case ERROR: 
     ;//TODO: Dispatch error, malformed 1st line 
     break; 
} 

是否有我可以申請的任何模式?或者其他的東西?

在此先感謝。

+0

你想達到什麼目的? –

+0

我必須解析一個HTTP請求(使用狀態機)。這解析了第一行(代碼不完整)。 – Juan

+0

雖然EJP的答案可能是最簡單和最有效的實施,但替代方案將是國家模式。每個狀態由一個狀態實例表示,狀態負責做1。實際工作(你的'if(c == x){build.append(c);}'東西)2.狀態改變 –

回答

0

注意在那裏測試輸入字符,並且在匹配的情況下每個狀態的代碼,接受輸入,並設置下一個狀態:

if (c == ????) { 
    builder.append(c); 
    firstState = ???? 
} 

你可以此邏輯移入的方法,消除每個州/輸入組合的switch三行代碼。

另外,注意每一個案件有:

else 
     firstState = FirstParserState.ERROR; 

您可以通過使用nextState變量消除每一個州這兩條線。在switch之前,您設置了nextState = FirstParserState.ERROR。當輸入匹配時,您將新狀態設置爲nextState而不是直接在firstState中。 如果沒有輸入匹配,單個狀態不需要做任何特殊的事情,因爲nextState已經是FirstParserState.ERROR。然後在switch後面設置firstParserState = nextState爲下一次迭代做準備。

0

您需要一個狀態表它將當前狀態和當前輸入字符映射到下一個狀態。然後你所要做的就是打開下一個狀態並採取適當的行動。

+0

謝謝我可以試試看,這取決於狀態模式的可能實現。 – Juan

0

我認爲你應該擺脫開關箱部分。您可以實現狀態機的設計模式,而不爲每一個狀態創建一個類,有一個更優雅的解決方案,如果你有很多狀態:根據枚舉狀態機

枚舉類實現ParserStateListener.java接口,其中包括方法是可以改變的對象」狀態。

public enum FirstParserState implements ParserStateListener{ 

INITIAL{ 
    public void onEventChange(char c, StringBuilder builder, FirstParserState nextState) { 
     if (c == 'g') { 
      builder.append(c); 
      nextState = FirstParserState.METHOD_G; 
     } else if (c == 'p') { 
      builder.append(c); 
      nextState = FirstParserState.METHOD_P; 
     } else 
      nextState = FirstParserState.ERROR; 

    } 
},METHOD_G{ 
    public void onEventChange(char c, StringBuilder builder, FirstParserState nextState) { 
     if (c == 'e') { 
      builder.append(c); 
      nextState = FirstParserState.METHOD_E; 
     } else 
      nextState = FirstParserState.ERROR; 

    } 
},METHOD_E{ 
    public void onEventChange(char c, StringBuilder builder, FirstParserState nextState) { 
     if (c == 't') { 
      builder.append(c); 
      nextState = FirstParserState.METHOD_T; 
     } else 
      nextState = FirstParserState.ERROR; 

    } 
},ERROR{ 
    public void onEventChange(char c, StringBuilder sb, FirstParserState nextState) { 
     // TODO Auto-generated method stub 

    } 
}; 

} 

這是監聽器類,以保持這將改變對象狀態」

public interface ParserStateListener { 

public void onEventChange(char c, StringBuilder sb, FirstParserState nextState); 

} 

然後,你可以寫你的客戶端代碼的行爲:

public void doOperations(){ 
    StringBuilder sb = new StringBuilder(); 

    FirstParserState firstParserState = FirstParserState.INITIAL; 
    firstParserState.onEventChange(c, sb, firstParserState);   

} 

這種做法僅僅是第一次看我不知道你的具體要求。如果你需要多次調用onEventChange(c, sb, firstParserState)方法,並且如果你已經知道你的轉換路徑,你可以把你的路由放到一個集合中,並通過調用這個方法來迭代。