如果在其他地方回答了这个问题,我们深表歉意;找不到足够的信息来说服自己最好的方法来做到这一点。我也意识到这是一个没有代码的冗长解释,但请告诉我是否应该编写一些示例代码来帮助演示我在做什么。
基本上:
- 使用 System.in/out 在 Java 中实现通信协议
- 当前的方法是实现一种状态模式,其中在上下文类中的 System.in 上实例化 Scanner
- 具体状态调用上下文方法从 Scanner 读取,然后根据 Scanner 返回的值适当地执行操作/转换状态
我使用状态模式的初衷是在从 System.in 解析这样的序列时简化代码(不要询问语法,这是我必须使用的东西):
- 命令名称=X
- 标题
- 标题信息行
- 内容
- 命令内容行
- 结束内容
- 结束命令
我通常为我期望收到的每种类型的命令定义一个具体的状态。以上述序列为例,我将有一个类似于 {WAITING_FOR_COMMAND, COMMAND_RECEIVED, PARSING_HEADER, PARSING_CONTENTS, PARSING_DONE, COMMAND_PROCESSED} 的状态集。我最初会在 WAITING_FOR_COMMAND,然后当收到“COMMAND NAME=X”时,我会转换到 COMMAND_RECEIVED,然后当“HEADER”进来时,我会转换到 PARSING_HEADER,等等。这种设计使得遍历所有边缘情况协议更容易,并且还使代码在协议被调整时易于更新/维护。显然比大量的 switch 语句和重复的边界检查要好得多。
我遇到的问题是,当我充实我的具体状态行为时,我发现自己在上下文类中声明了越来越多的状态变量,并且知道这可能很糟糕,因为我正在创建非常暴露的接口和非常高的联系上下文和具体的状态类。该协议中的命令序列可以任意长,我需要保存命令序列中每个项目传递的信息,直到命令序列完成。
以上面的命令序列为例,在“COMMAND ID=X”之后,我想在收到“ENDCOMMAND”并完全处理命令后保存值X以备将来使用。在“HEADER”之后,我想在收到“ENDCOMMAND”后保存标题信息以备将来使用,以供实际处理命令时使用。等等等等。现在只需将 commandId 和标头状态变量添加到上下文类中就可以了,但对我来说似乎并不干净或封装得很好。
有没有人对他们如何解决这个问题有任何高层次的建议?有没有更好的使用状态设计模式呢?
只是要注意一些我一直在玩的想法:
- 为每种类型的命令序列定义状态上下文,并在从 System.in 接收到相关命令时调用适当的上下文;这看起来几乎就像拥有巨大的开关块一样混乱,并且似乎过度复杂化了设计
- 设计支持复合 FSM 的成熟 FSM 架构,其中每个命令序列在总体 FSM 中占据其自己的 FSM;这对我来说似乎有点矫枉过正
- 为每个命令序列类型创建具有各种子类的 ProtocolCommand 对象;我可以在转换时将这些传递到每个状态,并在我进行过程中逐渐建立它们……但这会使状态接口变得混乱,并迫使所有状态摄取一个他们不一定会使用的参数
非常感谢!抱歉,这太冗长了,如果我能澄清什么,请告诉我。