2016-12-28 1 views
1

Ich überprüfe einige Dokumentation auf Baumstrukturen und einige entsprechende Antworten auf das Thema hier auf stackoverflow.com, zum Beispiel this one und sie verwenden meist Rohtypen oder nur einen bestimmten Typ, der nicht arbeite für mein Problem. Ich habe eine Datei, die Meta als XML speichert, also war das Parsen kein Problem, aber ich brauche immer noch eine saubere Datenstruktur, um die tatsächlichen Informationen zu speichern.Vermeiden Sie die Verwendung von Prüfungen für instanzbezogene und rohe Typen

Der eigentliche Teil der Datei

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

Die Datenstruktur I mit kam

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

So könnte man vorschlagen, wie es sauberer zu machen, ohne rohe Typen mit wenn es eindeutig nicht notwendig ist und vermeiden Sie instanceof? Oder noch besser, zeig mir bitte, wo du mehr darüber lesen kannst.

Argumentative Kommentare würden viel mehr geschätzt werden, anstatt Down-Voting, wenn aus irgendeinem Grund das Thema nicht von Interesse ist.

+0

Ja, Sie sollten die Verwendung von 'instaceof' vermeiden, bis Sie beweisen können, dass es die beste Option ist. In diesem Fall ist es nicht, aber es scheint ein Nebeneffekt eines Designproblems zu sein. Können Sie den von Ihnen erwähnten Baum erklären und erklären, warum Sie eine Liste als potenziellen Wert haben? – ChiefTwoPencils

Antwort

1

Composite Pattern für Ihren Fall unter Berufung auf "Design Patterns" GoF

Compose Objekte in Baumstrukturen geeignet sein Teil-Ganzes-Hierarchien zu repräsentieren. Composite können Kunden einzelne Objekte und Zusammensetzungen von Objekten einheitlich behandeln.

Der folgende Code verbindet Ihre Baumstruktur mit Composite Pattern angewendet.

/** 
* 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); 

} 
Verwandte Themen