java界面设计:如何处理有状态处理

时间:2009-03-31 18:13:01

标签: java design-patterns interface

我在为应用程序的特定部分设计一个好的架构时遇到了麻烦,特别是在涉及维护状态的情况下。

我有一组解析操作:

我的班级Reader将一个数据块读入一个缓冲区并处理整个控制流程。 我的班级Parser获取缓冲区中的数据块和ParsedDataHandler,并将其划分为较小的块,以便ParsedDataHandler进行管理。

ParsedDataHandler是我试图设计的界面;我想我想做这样的事情(“BlockInfo”代表一些包含各种状态位的数据结构,其中包含一个包含整个原始数据块的ByteBuffer。“ChunkMetadata”表示包括块内每个块的位置的信息,以及Parser已确定的关于块的任何其他信息

interface ParsedDataHandler
{
    void beginBlock(BlockInfo bi);
    void handleParsedData(BlockInfo bi, ChunkMetadata m);
    void endBlock(BlockInfo bi);
}

所以Reader将调用ParsedDataHandler.beginBlock()让它在块的开头设置任何状态,并且承诺保留BlockInfo常量的指定部分(可能全部),直到它成为匹配对ParsedDataHandler.endBlock()的调用 - 之后它可能会为下一个块重用数据缓冲区。 Parser运行数据块并根据预定义的数据协议将其拆分为块,并且将针对每个块多次调用ParsedDataHandler.handleParsedData()。合同包含一个保持固定的缓冲区的一个原因是ParsedDataHandler可以在开头或结尾复制整个数据块,并且当它们是时,不必将块重新组装到一个块中。一直在一起。

所以责任分工:

  • Reader负责管理整个例行程序和读取数据,它不会关心其他任何事情。
  • Parser是将数据块拆分成块的东西,它不关心如何处理它们或数据如何到达那里
  • ParsedDataHandler是我正在设计的界面,以便具体的类可以实现它并正常工作,没有ReaderParser关心它的作用,或者没有关心它如何将块分成块或数据来自何处。

我的问题是,维护任何状态的负担是否应该在实现ParsedDataHandler的类上并且不在BlockInfo之外?如果我的接口的语义包括BlockInfo中的原始数据块在beginBlock()和endBlock()的调用之间不会改变的事实,那么我应该只将它传递给beginBlock()而不是其他调用吗?或者为了方便起见可以发送它吗?

是否有更好的设计模式来处理这种情况?

1 个答案:

答案 0 :(得分:2)

首先,您的实现非常接近State Pattern的经典示例。我看到的唯一问题是BlockInfo的作用。

如果在步骤之间更改BlockInfo,那么您的实现就是您需要做的。看看我引用的维基百科文章。在Mousedown,MouseMove和MouseUp之间更改了点,因此它必须是抽象工具的参数。

如果在步骤之间没有更改BlockInfo,那么您需要考虑几件事情。

如果实现ParsedDataHandler的类正在初始化BlockInfo结构的任何部分,那么我将其分离并使其成为该类的私有成员,并且只允许BlockInfo传递解析过程外部的初始化数据。

如果BeginBlock正在修改BlockInfo并将其传递给后续例程,那么您应该克隆BlockInfo,将其内部存储在实现ParsedDataHandler的类中。然后从参数列表中删除它。

如果之后需要BlockInfo,我会创建一个返回内部BlockInfo的readonly属性。

根据您的问题,我猜您应该将BlockInfo传递给BeginBlock并在内部存储它。从其他方法的参数中消除它,然后添加readonly属性,如果您需要检索它。