改进状态机
Improving state machine
因此,我将这个状态机(在下一个代码中,一些状态由于尚未完成而丢失)具有许多几乎相同的状态。
我确信一定有更好的方法来实现这一点,但我找不到(可能 类 但我不确定)。
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;
}
有没有我可以应用的模式?或者什么?
提前致谢。
注意每个状态下测试输入字符的代码,如果匹配,则接受输入并设置下一个状态:
if (c == ????) {
builder.append(c);
firstState = ????
}
您可以将此逻辑移动到一个方法中,并从 switch
中为每个 state/input 组合删除三行代码。
此外,请注意每个案例都有:
else
firstState = FirstParserState.ERROR;
您可以使用 nextState
变量从每个状态中删除这两行。在 switch
之前设置 nextState = FirstParserState.ERROR
。当输入匹配时,您可以在 nextState
中设置新状态,而不是直接在 firstState
中设置。
如果没有输入匹配,各个州不需要做任何特殊的事情,因为 nextState
已经是 FirstParserState.ERROR
。然后在 switch
之后设置 firstParserState = nextState
为下一次迭代做准备。
您需要一个状态table,它将当前状态和当前输入字符映射到下一个状态。然后你所要做的就是切换到下一个状态并采取适当的行动。
我认为你应该去掉 switch case 部分。您可以在不为每个状态创建 class 的情况下实现状态机设计模式,如果您有多个状态,还有一个更优雅的解决方案:基于枚举的状态机
Enum class 实现 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
}
};
}
这是侦听器 class 以保持将更改对象状态的操作'
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)
方法,并且你已经知道你的转换路径,你可以将你的路由放入一个集合中,然后通过调用这个方法来迭代。
因此,我将这个状态机(在下一个代码中,一些状态由于尚未完成而丢失)具有许多几乎相同的状态。 我确信一定有更好的方法来实现这一点,但我找不到(可能 类 但我不确定)。
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;
}
有没有我可以应用的模式?或者什么?
提前致谢。
注意每个状态下测试输入字符的代码,如果匹配,则接受输入并设置下一个状态:
if (c == ????) {
builder.append(c);
firstState = ????
}
您可以将此逻辑移动到一个方法中,并从 switch
中为每个 state/input 组合删除三行代码。
此外,请注意每个案例都有:
else
firstState = FirstParserState.ERROR;
您可以使用 nextState
变量从每个状态中删除这两行。在 switch
之前设置 nextState = FirstParserState.ERROR
。当输入匹配时,您可以在 nextState
中设置新状态,而不是直接在 firstState
中设置。
如果没有输入匹配,各个州不需要做任何特殊的事情,因为 nextState
已经是 FirstParserState.ERROR
。然后在 switch
之后设置 firstParserState = nextState
为下一次迭代做准备。
您需要一个状态table,它将当前状态和当前输入字符映射到下一个状态。然后你所要做的就是切换到下一个状态并采取适当的行动。
我认为你应该去掉 switch case 部分。您可以在不为每个状态创建 class 的情况下实现状态机设计模式,如果您有多个状态,还有一个更优雅的解决方案:基于枚举的状态机
Enum class 实现 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
}
};
}
这是侦听器 class 以保持将更改对象状态的操作'
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)
方法,并且你已经知道你的转换路径,你可以将你的路由放入一个集合中,然后通过调用这个方法来迭代。