我使用Hibernate進行持久化。Java Hibernate:什麼是更好的設計來擺脫鑄造
假設我有一個包含關於文檔及其製造(打印,或者通過電子郵件發送)所需的信息的信息的實體。就像這樣:
這裏的問題是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 ......)。
第二個在這個意義上是更好的:一旦你添加新的配置,編譯器將引導您完成整個過程:首先,你將需要實現在配置本身適當的方法,然後在所有的訪問者類。在另一方面,這是很尷尬的,我基本上是通過服務於實體...
所以我覺得我治標,而不是問題。也許設計本身需要一些改變?但我不知道如何可以改善......
不幸的是你的問題是:你用java。 Java遠非完美的語言,有時你不得不使用一些骯髒的技巧。 – talex
我會用一個圖書館來抽象所有東西,而不必去考慮這些沉悶的東西。我最終會用'objectMapper.toXML(myDocumentInformation)'(作爲一個例子),並且可以專注於更重要的設計問題。 – Kayaman