我想实现一个应用程序,其中我有各种可以解释为XML字符串的对象。首先,我想到创建一个接口,使每个对象实现两个方法:
public abstract Element toXML();
public abstract void fromXML(Element element);
第一个将对象信息转换为DOM元素,第二个将信息从DOM元素加载到对象。 我最终在每个子类中定义了一个静态String,其中包含元素的TAG,因此我决定将接口转换为抽象类并为其提供更多功能:
public abstract class XmlElement implements Serializable {
protected static Document elementGenerator;
public String TAG = "undefined";
static {
try {
elementGenerator = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch (ParserConfigurationException e) {
StateController.getInstance().addLog(
new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
System.exit(1);
}
}
public abstract Element toXML();
public abstract void fromXML(Element element);
}
元素生成器在toXML方法中用于生成元素。我无法克服的这个设计的错误是TAG属性不能像我希望的那样变成静态,主要是因为我不想实例化每个子类的对象只是为了知道TAG它使用。 Java不允许覆盖静态属性或方法,这是解决这个问题的正确方法吗?
答案 0 :(得分:6)
您可能最好如下重构您的抽象类:
public abstract class XmlElement implements Serializable {
protected static Document elementGenerator = createElementGenerator();
protected static Document createElementGenerator() {
try {
elementGenerator = documentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch (ParserConfigurationException e) {
StateController.getInstance().addLog(new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
System.exit(1);
}
}
public abstract Element toXML();
public abstract void fromXML(Element element);
protected abstract String getTag();
}
这会强制子类自己定义静态变量,并通过抽象getTag()方法将其返回给抽象类。我担心的一件事是,就我看来,elementGenerator不是线程安全的,因为它在XmlElement的所有子类的所有实例之间共享,这可能是一个问题。
您正在做的事情似乎存在其他设计问题,因为您只能拥有一个父类,具有执行繁重任务的实用程序类的接口可能是更好的解决方案。另外,我不确定您打算如何使用TAG变量。
答案 1 :(得分:3)
实际上,我的第一个问题是你的elementGenerator,因为它是静态的,将是一个单独的,并且由于它将在文档生成期间保持状态,你将在试图使用它的不同实例之间产生冲突。也许我错过了什么?
我也不确定通过使TAG属性为静态来使您更容易实现的情况。您是否可能有一堆Class对象(可能代表各种子类的类),您希望从中获取标记类型而无需实例化?这似乎......很奇怪。难道你没有子类的实际实例(这样你可以简单地使用每个人需要实现的抽象getTag()方法吗?
答案 2 :(得分:0)
如下:
public abstract class TaggedXmlElement implements XmlElement {
private final String tag;
TaggedXmlElement(String tag) {
this.tag = tag;
}
public String getTag() {
return tag;
}
}
public final class DomXmlElement extends TaggedXmlElement {
private static Map<String, DomXmlElement> CACHE = new ConcurrentHashMap<String, DomXmlElement>();
private final Document generator;
private DomXmlElement(String tag) {
super(tag);
try {
generator = documentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch (ParserConfigurationException e) {
StateController.getInstance().addLog(new Log(Log.Type.ERROR, "Couldn't load XML parser: " + e));
System.exit(1);
}
}
public static DomXmlElement getInstance(String tag) {
if(tag == null) {
throw new IllegalArgumentException("tag::null");
}
if(CACHE.contains(tag)) {
return CACHE.get(tag);
}
DomXmlElement element = new DomXmlElement(tag);
CACHE.put(tag, element);
return element;
}
// ... other stuff
}