Дизайн интерфейса Java: как обрабатывать обработку с сохранением состояния - PullRequest
1 голос
/ 31 марта 2009

У меня проблемы с проектированием хорошей архитектуры для определенной части моего приложения, особенно там, где требуется поддержание состояния.

У меня есть группа операций разбора:

Мой класс 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 (), а не на другие вызовы? или это нормально для удобства?

Есть ли лучший шаблон проектирования, чтобы справиться с такой ситуацией?

1 Ответ

2 голосов
/ 31 марта 2009

Во-первых, ваша реализация довольно близка к классическому примеру State Pattern . Единственная проблема, которую я вижу, это роль BlockInfo.

Если BlockInfo изменяется между этапами, то ваша реализация - это то, что вам нужно сделать. Посмотрите на статью в Википедии, на которую я ссылался. Точка изменяется между Mousedown, MouseMove и MouseUp, поэтому она должна быть параметром Abstract Tool.

Если BlockInfo не изменяется между этапами, вам нужно учесть несколько вещей.

Если класс, реализующий ParsedDataHandler, инициализирует какую-либо часть структуры BlockInfo, то я бы выделил это и сделал бы его закрытым членом класса, а просто передал бы BlockInfo данные инициализации, внешние по отношению к процессу синтаксического анализа.

Если BlockInfo модифицируется BeginBlock и передается последующим подпрограммам, вам следует клонировать BlockInfo, хранить его внутри в классе, реализующем ParsedDataHandler. Затем исключите его из списка параметров.

Если позже вам понадобится BlockInfo, я сделаю свойство только для чтения, которое будет возвращать внутренний BlockInfo.

Исходя из вашего вопроса, я думаю, вы должны передать BlockInfo в BeginBlock и сохранить его внутри. Исключите его из параметров других методов, затем добавьте свойство readonly, если вам нужно его извлечь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...