2016-04-27 6 views
2

Zum Beispiel habe ich eine Node Klasse für Binärbäume.Was ist der bessere Weg, um zusätzliche Informationen zu einem bestehenden Objekt hinzuzufügen?

public class Node { 
    public Node lchild; 
    public Node rchild; // public for convenience 
} 

Und jetzt habe ich einen Prozessor, der einige zusätzliche Informationen über Node Instanzen aufnehmen muss und verwenden sie nur privat. Sagen wir die Nummer in der Baumreihenfolge vor der Bestellung.

Ich denke, einen gerade Weg, es zu machen, ist ein Feld in der Klasse hinzuzufügen:

public class Node { 
    public Node lchild; 
    public Node rchild; 
    public int no; // the number in the pre-order tree traverse 
} 

Aber ich glaube, das ist definitiv eine schlechte Idee. Also, was ich verwende jetzt ist: Verwenden Sie ein Map<Node, Integer>

public class MyProcessor { 
    private Map<Node, Integer> no; 
    public void process1(Node node) { 
     int id = no.get(node); // or something like this 
    } 
} 

Sicherlich kann dieses Problem lösen. Aber mein Anliegen ist:

  1. Häufiger Zugriff auf eine Karte scheint weniger effizient? (verglichen mit dem Add-Field-Ansatz)
  2. Wenn ich mehrere Arten von Informationen brauche, muss ich mehrere Karten erstellen, was ein Alptraum zu sein scheint.

Also, gibt es einen besseren Weg bitte? Vielen Dank!

+0

* "Aber ich glaube, das ist definitiv eine schlechte Idee." * Warum? Wird 'Node' in anderen Prozessoren wiederverwendet? –

+0

@ T.J.Crowder Yeah, 'Node' ist weit verbreitet. – abcdabcd987

+4

Ich nehme an, Sie können 'Node' ableiten und so viele Informationen hinzufügen wie Sie wollen. – dejvuth

Antwort

2

Die beste Lösung wäre wahrscheinlich, das Node Objekt, das Sie haben, zu erweitern, dies ermöglicht es Ihnen, neue Funktionen zu nutzen und gleichzeitig bestehenden Code nicht zu brechen.

Sie können dies auch mit den Mustern Decorator und Factory koppeln, um einen transparenten und strukturierten Objekterstellungsprozess zu versuchen.

0

Es ist eine Frage der Trennung von Bedenken. Sind die Informationen, die Sie hinzufügen möchten, ein Problem des Knotens oder des Prozessors des Baumes?

würde ich sagen, die folgenden Aussagen beschreiben die Situation

  • der Baum hat Knoten (Zusammensetzung Aggregation)
  • der Knoten Knoten (Aggregation)
  • der Knoten Knoten info (Aggregation)
  • der Prozessor verarbeitet den Baum (Abhängigkeit)

Also würde ich die Info mit dem Knoten setzen oder assoziieren . Um einen gewissen Grad an flexbility zu haben, können Sie die Informationen über eine Erweiterung der Knoten

class ExtNode extends Node { 

    int no; 

} 

oder Dekorateur haben könnte:

class NodeDecorator { 

    Node node; 
    int no; 

    NodeDecorator(node){ 
     this.node = node; 
    } 
} 

Falls Sie für die Karte gehen, Effizienz sollte nicht Seien Sie in dieser Phase Ihr Anliegen. Der Zugriff auf Karten ist sehr effizient. Sie können später bei Bedarf optimieren.

Wenn zusätzliche Informationen hinzugefügt werden, können Sie eine neue Struktur definieren, z. B. NodeInfo, und alle Informationen dort eingeben und sie in die Map oder den Knoten einfügen, anstatt int.

Zum Beispiel

class NodeInfo { 
    int no; 
    String other; 
} 
0

Die zusätzliche Information wird an einen Prozessor der Knotenhierarchie spezifisch, so sollte es nicht in den Knoten (Trennung von Bedenken) Leck

Mögliche Lösungen:

  1. Verwenden Sie für diesen Prozessor eine parallele Baumstruktur

Da der Knoten eine Baumstruktur ist, wird eine parallele Struktur verwendet, die beim Besuch der Knotenstrukturen erstellt wird. Dieses parallele Element (ProcessedNode?) Würde die zusätzliche Information enthalten, einen Verweis auf die untergeordneten ProcessedNode-Knoten von Node und links/rechts.

Dies ist möglicherweise besser in Bezug auf Speicher und Zugriff (kein Map-Overhead), aber machen den Prozessor ein bisschen komplexer: Es würde ProcessedNode statt Node besuchen. Anstatt den nächsten Knoten zu besuchen, würde er einen ProcessedNode für den nächsten Knoten erstellen und den ProcessedNode aufrufen.

Sie können den ProcessedNode mit Lazy-Build erstellen, sodass der parallele Baum nach Bedarf erstellt wird.

Es ist nicht praktikabel, wenn die Knotenbaumstruktur mutiert ist und Sie die ProcessedNode-Informationen für mehr als die Dauer einer Verarbeitung beibehalten müssen.

  1. Verwenden einer Karte

Statt eine Karte pro zusätzliche Informationen haben, können Sie diese alle in einer Klasse-Details enthält die zusätzlichen Informationen, sammeln und eine einzelne Karte verwenden

Der Vorteil dieser Lösung ist die einfache Implementierung. Nachteil ist, dass wenn Sie die Karte behalten, müssen Sie pflegen, wenn ein Knoten verschwinden.

Die endgültige Wahl hängt davon ab, wie lange die zusätzlichen Details benötigt werden, wenn Sie nur die Informationen für die Dauer der Verarbeitung pflegen müssen, wird die Karte am Ende der Verarbeitung fallen gelassen, so die Kosten des Hinzufügens Elemente auf der Karte werden nicht verwendet.

Wenn das Erstellen einer Karte praktisch ist, bevor Sie mit einer alternativen Lösung optimieren, sollten Sie den tatsächlichen Overhead messen: Ist die Verstärkung den Aufwand wert?

0

Bei der Subklassifizierung sollten Sie "Getter-Methoden" für den Zugriff auf untergeordnete Knoten verwenden, damit die Unterklasse sie überschreiben kann.

public class Node { 
    protected Node left; 
    protected Node right; 

    public Node(Node left, Node right) { 
     this.left = left; 
     this.right = right; 
    } 

    public Node getLeft() { return left; } 
    public Node getRight() { return right; } 
} 

Und überschreiben Sie diese in einer Unterklasse, erstellen Sie bei Bedarf die untergeordneten Knoten.

public class DecoratedNode extends Node { 
    private Node original; 
    private int no = 0; 

    public DecoratedNode(Node n) { 
     super(null, null); 
     original = n; 
    } 

    @Override 
    public Node getLeft() { 
     if (left == null && original.getLeft() != null) 
      left = new DecoratedNode(original.getLeft()); 
     return left; 
    } 

    @Override 
    public Node getRight() { 
     if (right == null && original.getRight() != null) 
      right = new DecoratedNode(original.getRight()); 
     return right; 
    } 

    public int getNo() { return no; } 
    public void setNo(int no) { this.no = no; } 
} 

Dann übergeben new DecoratedNode(root) an die Prozessmethode.

Verwandte Themen