如果在其他地方回答了这个问题,很抱歉;找不到足够的信息来说服我自己做这件事的最佳方法。我还意识到这是一个冗长的解释,没有代码,但是让我知道我是否应该编写一些示例代码来帮助演示我正在做的事情。
基本上:
我使用状态模式的初衷是在解析来自System.in的序列时简化代码(不要问语法问题,这是我必须处理的):
我通常为我期望接收的每种类型的命令定义一个具体的状态。以上面的序列为例,我将有一个类似于{WAITING_FOR_COMMAND、COMMAND_RECEIVED、PARSING_HEADER、PARSING_CONTENTS、PARSING_DONE、COMMAND_PROCESSED}的状态集。我最初在WAITING_FOR_COMMAND中,然后当收到“NAME=X命令”时,我会转换到COMMAND_RECEIVED,然后当"HEADER“出现时,我会转换到PARSING_HEADER等等。这种设计使得遍历协议中的所有边缘情况变得更容易,并且使代码更容易更新/维护,以便在协议被调整时使用。显然比大规模的切换语句和重复的边界检查要好得多。
我遇到的问题是,我发现自己在上下文类中声明了越来越多的状态变量,因为我充实了自己的具体状态行为,并且知道这可能很糟糕,因为我正在创建非常公开的接口,并且在上下文和具体状态类之间建立非常高的联系。该协议中的命令序列可以任意长,我需要保存命令序列中每个项所传递的信息,直到命令序列完成为止。
以上面的命令序列为例,在“命令ID=X”之后,我希望在收到"ENDCOMMAND“之后保存值X供以后使用,并完全处理该命令。在" header“之后,我希望在收到"ENDCOMMAND”之后保存标题信息,以便在实际处理命令时使用。就这样等等。简单地将commandId和头状态变量添加到上下文类中就可以了,但在我看来,这一点都不干净,也没有很好的封装。
对于如何处理这个问题,有人有什么高层次的建议吗?有更好的使用状态设计模式吗?
我只是想指出一些我一直在玩的点子:
非常感谢!对不起,这件事太冗长了,如果我能澄清什么,请告诉我。
发布于 2012-07-03 19:16:58
对于这种解析方式,我使用了一个枚举,每个状态都使用了一个枚举。这里就是一个例子,http://vanillajava.blogspot.co.uk/2011/06/java-secret-using-enum-as-state-machine.html
interface Context {
ByteBuffer buffer();
State state();
void state(State state);
}
interface State {
/**
* @return true to keep processing, false to read more data.
*/
boolean process(Context context);
}
enum States implements State {
XML {
public boolean process(Context context) {
if (context.buffer().remaining() < 16) return false;
// read header
if(headerComplete)
context.state(States.ROOT);
return true;
}
}, ROOT {
public boolean process(Context context) {
if (context.buffer().remaining() < 8) return false;
// read root tag
if(rootComplete)
context.state(States.IN_ROOT);
return true;
}
}
}
public void process(Context context) {
socket.read(context.buffer());
while(context.state().process(context));
}发布于 2012-07-03 20:06:05
我首先要考虑以下几点:
https://stackoverflow.com/questions/11317603
复制相似问题