如何克服静态属性无法覆盖的事实?

时间:2009-12-08 15:44:27

标签: java design-patterns static override

我想实现一个应用程序,其中我有各种可以解释为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不允许覆盖静态属性或方法,这是解决这个问题的正确方法吗?

3 个答案:

答案 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

}