Java Hibernate: что будет лучшим дизайном, чтобы избавиться от кастинга
Я использую Hibernate для настойчивости.
Предположим, у меня есть объект, который содержит информацию о документе и необходимую информацию для его создания (либо печать, либо отправка по электронной почте). Именно так:
Проблема здесь заключается в том, что DocumentInformation содержит ссылку на абстрактный класс DocumentProductionConfiguration, а не на подклассы DocumentPrintConfiguration или DocumentEmailConfiguration.
Поэтому, когда мне действительно нужно получить подходящую конфигурацию, у меня есть два варианта: либо использовать instanceof + casting, либо использовать шаблон посетителя, чтобы обмануть Java, чтобы он фактически понимал во время выполнения, с какой конфигурацией он имеет дело.
Используя кастинг:
public class XmlBuilder{ public XMLMessage buildXmlMessage(DocumentInformation documentInformation){ if(documentInformation.getDocumentProductionConfiguration() instanceOf DocumentPrintConfiguration){ DocumentPrintConfiguration printConfig = (DocumentPrintConfiguration) documentInformation.getDocumentProductionConfiguration(); XMLMessageConfig xmlConfig = handlePrintConfig(printConfig); } } public XMLMessageConfig handlePrintConfig(DocumentPrintConfiguration printConfig){ ....build that XMLMessageConfig.... } }
Использование шаблона посетителя:
Мне нужно добавить новый интерфейс для XmlBuilder для реализации
public interface XmlBuilderVisitor<T> {
T handlePrintConfig(DocumentPrintConfiguration printConfig);
}
public class XmlBuilder implements XmlBuilderVisitor<XMLMessageConfig> {
@Override
public XMLMessageConfig handlePrintConfig(DocumentPrintConfiguration printConfig){
....build that XMLMessageConfig....
}
public XMLMessage buildXmlMessage(DocumentInformation documentInformation){
XMLMessageConfig xmlMessageConfig = documentInformation.getDocumentProductionConfiguration().buildConfiguration(this);
}
}
public abstract class DocumentProductionConfiguration{
public abstract <T> T buildConfiguration(XmlBuilderVisitor<T> visitor);
}
public class DocumentPrintConfiguration extends DocumentProductionConfiguration{
public <T> T buildConfiguration(XmlBuilderVisitor<T> visitor){
return visitor.handlePrintConfig(this);
}
}
Оба эти решения вроде как... Первое, потому что оно нарушает принцип открытого-закрытого (мне нужно всегда поддерживать эти ifs...).
Второй в этом смысле лучше: как только вы добавите новую конфигурацию, компилятор проведет вас через процесс: сначала вам нужно будет реализовать соответствующий метод в самой конфигурации, а затем во всех классах посетителей. С другой стороны, довольно неловко, что я в основном передаю служение сущности...
Поэтому я чувствую, что лечу симптомы, а не проблему. Может быть, сам дизайн нуждается в некоторых изменениях? Но я не уверен, как это можно улучшить...
1 ответ
Я бы порекомендовал толкать функциональность "ручки" в DocumentProductionConfiguration
и подклассы. Таким образом DocumentPrintConfiguration
будет содержать handle
функция, которая строит и возвращает XMLMessageConfig
, Тогда ваш XmlBuilder становится:
public class XmlBuilder{
public XMLMessage buildXmlMessage(DocumentInformation documentInformation){
XMLMessageConfig xmlConfig = documentInformation.getDocumentProductionConfiguration().handle();
}
}