Я хочу реализовать сетевой протокол. Чтобы получить поддерживаемую конструкцию, я ищу подходящие шаблоны.
Протокол основан на XML и должен быть прочитан с помощью java. Чтобы упростить обсуждение здесь, я беру пример грамматики:
<User>
<GroupList>
<Group>group1</Group>
<Group>group2</Group>
</GroupList>
</User>
Короткий вопрос: что такое хороший шаблон дизайна для разбора такой вещи?
Длинная версия: Я нашел этот и этот вопрос, где предлагаются разные шаблоны (в основном, государственный шаблон).
Мое фактическое (но недостающее) решение заключается в следующем: я создаю для каждой возможной записи в XML класс, содержащий данные и парсер. Таким образом, у меня есть User
, User.Parser
,... как классы. Далее есть ParserSelector
который имеет Map<String,AbstractParser>
в которой регистрируются все возможные подзаголовки. Для каждого анализатора создается и ParserSelector
экземпляр ParserSelector
. Например, ParserSelector
GroupList.Parser
имеет одну запись: Отображение из строки "Group"
в экземпляр Group.Parser
. Если бы я не использовал класс ParserSleector
, мне пришлось бы писать этот блок кода в каждый синтаксический анализатор.
Проблема заключается в том, как получить прочитанные данные в суперобъектах. Group.Parser
бы создать Group
объектов с содержанием group1
. Теперь этот объект должен быть зарегистрирован в объекте GroupList
. Я читал об использовании шаблонов Visitor или Observer, но не понимаю, как они могут поместиться здесь.
Ниже я даю некоторый псевдо-код, чтобы увидеть проблему. Вы видите, что мне нужно проверить через instanceof
для типа, поскольку статически существует информация о типе, недоступная.
Я думал, что это должно быть возможно решить с использованием полиморфизма в java в более чистом (более ремонтопригодном) способе. Я всегда сталкиваюсь с проблемой, что java делает только динамическое связывание при переопределении. Таким образом, я не могу добавить параметр к XMLParser.parse(...)
чтобы разрешить "удаленное обновление", как в подход "посетитель/наблюдатель".
Боковое замечание: настоящая грамматика является "глубокой", то есть таковой, что имеется довольно много XML-записей (здесь только три: User
, GroupList
и Group
), в то время как в большинстве из них может быть только очень мало разных подстатей (User
и GroupList
могут здесь есть только одна подстанция, а сама Group
содержит только текст).
Вот несколько строк кода java для объяснения проблемы:
class User extends AbstractObject {
static class Parser implements XMLParser {
ParserSelector ps = ...; // Initialize with GroupList.Parser
void parse(XMLStreamReader xsr){
XMLParser p = ps.getParser(...); // The corresponding parser.
// We know only that it is XMLParser statically.
p.parse(...);
if(p instanceof GroupList.Parser){
// Set the group list in the User class
}
}
}
}
class GroupList extends AbstractObject{...}
class Group extends AbstractObject{...}
class ParserSelector{
Map<String,XMLParser> = new Map<>();
void registerParser(...){...} // Registers a possible parser for subentries
XMLParser getParser(String elementName){
return map.get(elementName); // Returns the parser registered with the given name
}
}
interface XMLParser {
void parse(XMLStreamReader xsr);
}
abstract class AbstractObject{}
Чтобы закончить этот вопрос:
Я закончил с JAXB
. На самом деле я не знал о том, что он позволяет легко создавать XML-схему из исходного кода Java (используя аннотации).
Таким образом, мне просто нужно написать код с классическими java-объектами, которые используются для передачи. Затем API обрабатывает преобразование в и из XML довольно хорошо.