【问题标题】:Avoid using checks for instance-relating and raw types避免对实例相关类型和原始类型使用检查
【发布时间】:2016-12-28 01:34:33
【问题描述】:

我在 stackoverflow.com 上重新检查了一些关于树结构的文档和一些关于该主题的相关答案,例如this one,它们大多使用原始类型或仅使用一种不适用于我的问题的特定类型。我有一个将元数据存储为 XML 的文件,因此解析不是问题,但我仍然需要一个干净的数据结构来存储实际信息。

文件的实际部分

<File>
  <Meta>
    <Generator>default</Generator>
    <HeaderHash>110EbosCOut9ooqtIza4yHdT9xx+wUAp1VMfPqpQKwM=</HeaderHash>
    <Color/>
    <MemoryProtection>
      <ProtectTitle>False</ProtectTitle>
      <ProtectUserName>False</ProtectUserName>
      <ProtectPassword>True</ProtectPassword>
      <ProtectURL>False</ProtectURL>
      <ProtectNotes>False</ProtectNotes>
    </MemoryProtection>
    <CustomIcons/>
    <Binaries />
    <CustomData/>
  </Meta>
</<File>

我想出的数据结构

public class MetadataEntry {

    public MetadataEntry() {
        this.entity = new Entry();
    }

    private class Entry<T> {
        private String name;
        private T value;
        private boolean isGroup;

        private void setValue(T value) {

            if (value instanceof String) {
                this.value = value;
                this.isGroup = false;
            }

            if (value instanceof MetadataEntry) {
                if (isGroup()) {
                    ((List<MetadataEntry>) this.value).add((MetadataEntry) value);
                } else {
                    this.value = (T) new ArrayList<MetadataEntry>();
                    this.isGroup = true;
                    setValue(value);
                }
            }
        }

    }

    private Entry entity;


    public void setName(String name) {
        this.entity.name = name;
    }

    public String getName() {
        return this.entity.name;
    }

    public void setValue(String value) {
        entity.setValue(value);
    }

    public void setValue(MetadataEntry value) {
        entity.setValue(value);
    }

    public boolean isGroup() {
        return this.entity.isGroup;
    }

    public List<MetadataEntity> getChildNodes() {
        if (isGroup()) {
            return (List<MetadataEntry>) this.entity.value;
        }

        return null;
    }

    public String getValue() {
        if (!isGroup()) {
            return (String) this.entity.value;
        }

        return null;
    }
}

那么,如果显然没有必要,您能否建议如何使其更清洁,而不使用原始类型,并避免使用instanceof?或者更好地指出我在哪里可以阅读更多相关信息。

如果由于某种原因对主题不感兴趣,那么争论的 cmets 将受到更多的赞赏,而不是投反对票。

【问题讨论】:

  • 是的,你应该避免使用instaceof,直到你能证明它是最好的选择。在这种情况下,它不是,但它看起来是设计问题的副作用。您能否澄清您提到的树并解释为什么您将列表作为潜在价值?

标签: java tree


【解决方案1】:

Composite Pattern 将适合您的情况,引用《Design Patterns》GoF

将对象组合成树结构以表示部分-整体层次结构。 Composite 让客户可以处理单个对象和对象的组合 均匀。

以下代码将应用Composite Pattern 的树结构组合在一起。

/**
 * declares the interface for objects in the composition
 * @param <T>
 */
interface MetaEntry<T> extends Iterable<MetaEntry<T>> {
    T getName();
    MetaEntry<T> setName(T name);
    T getValue();
    MetaEntry<T> setValue(T name);
    MetaEntry<T> add(MetaEntry<T> entry);
    MetaEntry<T> remove(MetaEntry<T> entry);
}
/**
 * represents leaf objects in the composition. A leaf has no children.
 * @param <T>
 */
class SimpleMetaEntry<T> implements MetaEntry<T> {
    T name;
    T value;
    @Override
    public T getName() {
        return name;
    }

    @Override
    public MetaEntry<T> setName(T name) {
        this.name = name;
        return this;
    }

    @Override
    public T getValue() {
        return value;
    }

    @Override
    public MetaEntry<T> setValue(T value) {
        this.value = value;
        return this;
    }

    @Override
    public MetaEntry<T> add(MetaEntry<T> entry) {
        throw new UnsupportedOperationException();
    }

    @Override
    public MetaEntry<T> remove(MetaEntry<T> entry) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Iterator<MetaEntry<T>> iterator() {

        // we want to treat all objects uniformly.
        return  new Iterator<MetaEntry<T>>() {
            @Override
            public boolean hasNext() {
                return false;
            }

            @Override
            public MetaEntry<T> next() {
                return null;
            }
        };
    }

    @Override
    public String toString() {
        return "<" + name + (value == null ? "/>" : ">" + value + "</" + name + ">\n");
    }
}

/**
 * defines behavior for components having children.
 * @param <T>
 */
class CompositeMetaEntry<T> implements MetaEntry<T> {
    T name;
    T value;
    List<MetaEntry<T>> list = new ArrayList<MetaEntry<T>>();
    @Override
    public T getName() {
        return name;
    }

    @Override
    public MetaEntry<T> setName(T name) {
        this.name = name;
        return this;
    }

    @Override
    public T getValue() {
        return value;
    }

    @Override
    public MetaEntry<T> setValue(T value) {
        this.value = value;
        return this;
    }

    @Override
    public MetaEntry<T> add(MetaEntry<T> entry) {
       list.add(entry);
        return this;
    }

    @Override
    public MetaEntry<T> remove(MetaEntry<T> entry) {
        list.remove(entry);
        return this;
    }

    @Override
    public Iterator<MetaEntry<T>> iterator() {
        return  list.iterator();
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();

        builder.append("<" + name + ">");

        for(MetaEntry<T> metaEntry : this) {
            builder.append(metaEntry.toString());
        }
        builder.append("</" + name + ">");

        return builder.toString();
    }
}

public static void main(String[] args) throws Exception {
        MetaEntry<String> compositeMetaEntry = new CompositeMetaEntry<String>();
        compositeMetaEntry.setName("File");
        compositeMetaEntry.add(
                new CompositeMetaEntry<String>().setName("Meta").add(
                        new SimpleMetaEntry<String>().setName("Generator").setValue("default")
                ).add(
                        new SimpleMetaEntry<String>().setName("HeaderHash").setValue("110EbosCOut9ooqtIza4yHdT9xx+wUAp1VMfPqpQKwM=")
                ).add(
                        new SimpleMetaEntry<String>().setName("Color")
                ).add(
                        new CompositeMetaEntry<String>().setName("MemoryProtection").add(
                                new SimpleMetaEntry<String>().setName("ProtectTitle").setValue("False")
                        ).add(
                                new SimpleMetaEntry<String>().setName("ProtectUserName").setValue("False")
                        ).add(
                                new SimpleMetaEntry<String>().setName("ProtectPassword").setValue("True")
                        ).add(
                                new SimpleMetaEntry<String>().setName("ProtectURL").setValue("False")
                        ).add(
                                new SimpleMetaEntry<String>().setName("ProtectNotes").setValue("false")
                        )
                ).add(
                        new SimpleMetaEntry<String>().setName("CustomIcons")
                ).add(
                        new SimpleMetaEntry<String>().setName("Binaries")
                ).add(
                        new SimpleMetaEntry<String>().setName("CustomData")
                )
        );

        System.out.println(compositeMetaEntry);

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多