У меня проблемы с проектированием хорошей архитектуры для определенной части моего приложения, особенно там, где требуется поддержание состояния.
У меня есть группа операций разбора:
Мой класс 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
- это интерфейс, который я пытаюсь спроектировать так, чтобы конкретные классы могли его реализовать и работать правильно, без Reader
или Parser
заботы о том, что он делает, или без заботы о том, как разделить блок на куски или откуда пришли данные.
У меня вопрос: должно ли быть бремя поддержания какого-либо состояния для класса, реализующего ParsedDataHandler
и не входящего в BlockInfo? И если семантика моего интерфейса включает в себя тот факт, что блок необработанных данных в BlockInfo не изменится между вызовами beginBlock () и endBlock (), должен ли я тогда передавать его только в beginBlock (), а не на другие вызовы? или это нормально для удобства?
Есть ли лучший шаблон проектирования, чтобы справиться с такой ситуацией?