Один из вариантов - создать класс, который выбирает соответствующий синтаксический анализатор в зависимости от формата данных. Например, предположим, что есть два формата, в которых могут отображаться данные об ученике: (1) JSON и (2) XML:
public class Student {
// ...
}
public interface StudentParser {
public Student parse(String data);
}
public class JsonStudentParser {
@Override
public Student parse(String data) {
// ...
}
}
public class XmlStudentParser {
@Override
public Student parse(String data) {
// ...
}
}
public class StudentDeserializer {
private final StudentParser jsonParser = new JsonStudentParser();
private final StudentParser xmlParser = new XmlStudentParser();
public Student deserialize(String data) {
if (isJson(data)) {
return jsonParser.parse(data);
}
else if (isXml(data)) {
return xmlParser.parse(data);
}
else {
throw new UnknownStudentFormatException();
}
}
}
public class UnknownStudentFormatException extends RuntimeException {
// ...
}
Решение о разграничении данных JSON и XML оставлено на ваше усмотрение, но структура является важной частью выше. Существует StudentParser
для каждого из форматов, доступных в системе, и правильный StudentParser
выбирается в зависимости от того, какой формат обнаружен. Я не уверен, существует ли официальное название для такого шаблона, но я слышал, что раньше его называли Switchboard .
Дополнительно
Если вы хотите, чтобы StudentDeserializer
был более универсальным (не зависит только от JSON и XML), вы можете переместить логику для принятия решения, какой формат может обрабатывать реализация StudentParser
, из StudentDeserializer
в саму реализацию. Затем StudentDeserializer
может содержать список StudentParser
объектов, которые зарегистрированы, и выбрать тот, который может использоваться для анализа данных. Например (Student
и UnknownStudentFormatException
такие же, как в предыдущем примере и были опущены):
public interface StudentParser {
public Student parse(String data);
public boolean canHandle(String data);
}
public class JsonStudentParser {
@Override
public Student parse(String data) {
// ...
}
@Override
public boolean canHandle(String data) {
// ... is JSON? ...
}
}
public class XmlStudentParser {
@Override
public Student parse(String data) {
// ...
}
@Override
public boolean canHandle(String data) {
// ... is XML? ...
}
}
public class StudentDeserializer {
private final List<StudentParser> parsers = new ArrayList<>();
public void registerParser(StudentParser parser) {
parsers.add(parser);
}
public Student deserialize(String data) {
return parsers.stream()
.filter(parser -> parser.canHandle(data))
.findFirst()
.orElseThrow(() -> new UnknownStudentFormatException())
.parse(data);
}
}
Затем можно зарегистрировать StudentParser
реализаций:
JsonStudentParser jsonParser = new JsonStudentParser();
XmlStudentParser xmlParser = new XmlStudentParser();
StudentDeserializer deserializer = new StudentDeserializer();
deserializer.registerParser(jsonParser);
deserializer.registerParser(xmlParser);
deserializer.deserialize(someData);
Если у вас есть какая-то инфраструктура внедрения зависимостей (DI), вы можете автоматически подключать реализации StudentParser
вместо их ручной регистрации.