我使用Hibernate进行持久化。
假设我有一个实体,其中包含有关文档的信息以及生成文档的必要信息(打印或通过电子邮件发送)。像这样:
这里的问题是DocumentInformation保存对抽象类DocumentProductionConfiguration的引用,而不是对子类DocumentPrintConfiguration或DocumentEmailConfiguration的引用。
因此,当我真正需要获得适当的配置时,我有两个选择:使用instanceof + cast或使用访问者模式来欺骗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 ......)。
在这个意义上的第二个更好:一旦你添加新配置,编译器将指导你完成整个过程:首先,你需要在配置本身,然后在所有访问者类中实现适当的方法。另一方面,我基本上将服务传递给实体是非常尴尬的......
所以我觉得我正在治疗症状而不是问题。也许设计本身需要一些变化?但我不确定它是如何改进的......
答案 0 :(得分:0)
我建议将“句柄”功能推送到DocumentProductionConfiguration
和子类中。因此DocumentPrintConfiguration
将包含构建并返回handle
的{{1}}函数。然后你的XmlBuilder变成:
XMLMessageConfig