我使用Hibernate进行持久化。

假设我有一个实体,其中包含有关文档的信息以及生成文档的必要信息(打印或通过电子邮件发送)。像这样:
java - Java Hibernate:摆脱类型转换的更好的设计是什么-LMLPHP

这里的问题是DocumentInformation拥有对抽象类DocumentProductionConfiguration的引用,而不是对DocumentPrintConfiguration或DocumentEmailConfiguration的子类的引用。

因此,当我实际上需要获得适当的配置时,我有两种选择:要么使用instanceof +强制转换,要么使用访问者模式来欺骗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 ...)。

从这个意义上讲,第二个方法更好:一旦添加了新的配置,编译器将引导您完成该过程:首先,您需要在配置本身中实现适当的方法,然后在所有访问者类中实现。另一方面,我基本上将服务传递给实体非常尴尬...

所以我觉得我在治疗症状而不是问题。也许设计本身需要一些更改?但是我不确定如何改进...

最佳答案

我建议将“句柄”功能推入DocumentProductionConfiguration和子类中。这样,DocumentPrintConfiguration将包含一个handle函数,该函数将生成并返回一个XMLMessageConfig。当您的XmlBuilder变为:

public class XmlBuilder{
    public XMLMessage buildXmlMessage(DocumentInformation documentInformation){
        XMLMessageConfig xmlConfig = documentInformation.getDocumentProductionConfiguration().handle();
    }
}

09-06 13:37