所以我这个状态机(在下一个代码中有些状态因为它们还没有完成而丢失)有很多几乎相同的状态。 我确信必须有更好的方法来实现这一目标,但我找不到它(可能有课程,但我不确定)。
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)
注意每个状态中的代码,用于测试输入字符,如果匹配,则接受输入并设置下一个状态:
if (c == ????) {
builder.append(c);
firstState = ????
}
您可以将此逻辑移动到某个方法中,并为每个状态/输入组合从switch
中删除三行代码。
另外,请注意每个案例都有:
else
firstState = FirstParserState.ERROR;
您可以使用nextState
变量从每个州消除这两行。在switch
设置nextState = FirstParserState.ERROR
之前。当输入匹配时,您可以在nextState
中设置新状态,而不是直接在firstState
中设置。
如果没有输入匹配,则各个州不需要执行任何特殊操作,因为nextState
已经是FirstParserState.ERROR
。然后在switch
之后设置firstParserState = nextState
以准备下一次迭代。
答案 1 :(得分:0)
您需要一个状态表,它将当前状态和当前输入字符映射到下一个状态。然后你所要做的就是打开下一个状态并采取适当的行动。
答案 2 :(得分:0)
我认为你应该摆脱开关盒部分。您可以在不为每个州创建类的情况下实现状态机设计模式,如果您有许多状态,还有一个更优雅的解决方案:基于枚举的状态机
Enum类实现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)
方法,并且已经知道了转换路径,则可以将路径放到集合中,然后通过调用此方法进行迭代。