代码之家  ›  专栏  ›  技术社区  ›  eliocs

如何巧妙地克服静态属性不能被滥用的事实?

  •  4
  • eliocs  · 技术社区  · 16 年前

    我想实现一个应用程序,其中我有各种可以解释为XML字符串的对象。首先,我想制作一个接口,使每个对象实现两种方法:

    public abstract Element toXML();
    public abstract void fromXML(Element element);
    

    第一个将对象信息转换为DOM元素,第二个将信息从DOM元素加载到对象。 我最终在每个子类中定义了一个静态字符串,其中包含元素的标记,因此我决定将接口转换为抽象类,并赋予它更多的功能:

    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方法中使用元素发生器生成元素。我无法克服的这种设计的缺点是标记属性不能像我希望的那样被设置为静态的,主要是因为我不想仅仅为了知道它使用的标记而实例化和对象每个子类。 Java不允许重写静态属性或方法,这是克服这一问题的正确方法吗?

    3 回复  |  直到 16 年前
        1
  •  6
  •   Gennadiy    16 年前

    您最好将抽象类重构如下:

    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();
    }
    

    这将强制子类定义静态变量本身,并通过abstract gettag()方法将其返回到抽象类。我担心的一件事是,在我看来,elementGenerator不是线程安全的,因为它在所有可能是问题的xmlement子类的实例中都是共享的。

    由于您只能有一个父类,因此您所做的工作似乎还有其他设计问题,与执行重载提升的实用程序类的接口可能是更好的解决方案。另外,我不确定您计划如何使用标记变量。

        2
  •  3
  •   Jacob Mattison    16 年前

    实际上,我在这里首先要关注的是,您的元素生成器,因为它是静态的,将是单例的,并且由于它将在文档生成期间保持状态,所以您将在尝试使用它的不同实例之间遇到冲突。也许我错过了什么?

    我也不确定您试图通过使标记属性为静态属性来简化的情况。您是否可能有一系列的类对象(可能表示各种子类的类)想要从中获取标记类型而不需要实例化?似乎…奇怪的。您不会有子类的实际实例(这样您就可以简单地拥有一个抽象gettag()方法,每个方法都需要实现吗?

        3
  •  0
  •   Droo    16 年前

    比如:

    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
    
    }
    
    推荐文章