2009-03-10 11 views
7

Ich arbeite mit etwas Code, der einen Kind-Knoten zu seinem Elternteil im Konstruktor des Kindes hinzufügt. Der Code sieht etwa so aus:Bewährtes Verfahren: Hinzufügen eines untergeordneten Knotens zu einem übergeordneten Element im untergeordneten Konstruktor oder nicht?

Klasse:

class Node1 { 
    public Node1(Node1 parent, String name) { 
    if(parent != null) { 
     parent.add(this); 
    } 
    this.parent = parent; 
    } 

    private void add(Node1 child) { 
    children.add(child); 
    } 
} 

Verbrauch:

Node1 parent = new Node1(null, "parent"); 
Node1 child1 = new Node1(parent, "child1"); 
Node1 child2 = new Node1(parent, "child2"); 

Durch es auf diese Weise dem Benutzer der Klasse Umsetzung Node1 hat nicht explizit den untergeordneten Knoten hinzufügen (weniger Code) zu seinem Elternteil, und Sie haben garantiert, dass ein Kindknoten einen Elternteil hat.

Ich persönlich würde nicht so geschrieben haben, aber mehr wie folgt aus:

class Node2 { 
    public Node2(String name) { 
    } 

    public void add(Node2 child) { 
    children.add(child); 
    child.setParent(this); 
    } 
} 

Node2 parent = new Node2("parent"); 
Node2 child1 = new Node2("child1"); 
parent.add(child1); 
Node2 child2 = new Node2("child2"); 
parent.add(child2); 

So ist meine Frage, ist dies eine gute Idee, es zu implementieren, wie in der Klasse Node1 oder gibt es gezeigt jede Einwände, es so zu machen? Oder gibt es keinen Grund, warum man besser ist als der andere?

Antwort

11

Ich persönlich mag das erste Beispiel nicht, weil Sie einen Knoten hinzufügen, der noch nicht "bereit" ist (da der Konstruktor die Ausführung nicht beendet hat). In den meisten Fällen wird es funktionieren, aber in extremen Fällen können Sie Fehler haben, die ziemlich schwer zu finden sind.

+0

+1: Ziemlich viel, was ich gesagt habe. –

+0

Dies ist ein guter Punkt, es ist besser, dies nicht in einem Konstruktor zu verwenden. –

1

Ich denke, beide Implementierungen sind in Ordnung.

Die Frage ist mehr, wie Sie diese Klasse verwenden werden: Erstellen Sie zuerst eine Liste der Knoten und dann fügen Sie ihre Beziehungen hinzu oder werden Sie es in einer geordneten Weise tun, wie in Ihrem Beispiel?

Die zweite Lösung bietet mehr Flexibilität, auch wenn Sie Node1 als Superklasse verwenden möchten, sind Sie nicht an die Konstruktorsignatur gebunden.

2

Ich würde zweiten Fall als verwenden, dann kann ich später Kinder hinzufügen, aber nicht nur im Konstruktor.

0

Wenn Sie Knoten aus der TreeNode-Klasse ableiten, erhalten Sie automatisch die zweite Implementierung von Ihnen. Sie können Ihren "benutzerdefinierten" Treenode zur regulären Treeview-Klasse hinzufügen.

1

Ich mag nicht den ersten Fall - das Elternobjekt wird magisch nur durch die Weitergabe geändert - Sie müssen Code oder Dokumente lesen, um zu erkennen, dass dies geschieht. Wenn nur das übergeordnete Element übergeben wird, bedeutet dies, dass das Kind das übergeordnete Element kennt - nicht, dass das untergeordnete Element ebenfalls zur internen Liste des übergeordneten Elements hinzugefügt wird.

Zweites Beispiel ist besser. Sie könnten zurückkehren auch das Kind aus dem Betrieb ‚Hinzufügen‘ Betrieb zu ermöglichen Verkettungs wie:

Node2 child = parent.add(new Node2()); 
1

Ich sehe keinen Grund, warum nicht die beiden Ansätze für die Bequemlichkeit zu kombinieren:

class Node1 { 
    public Node1(String name, Node1 parent = null) { 
    this.name = name; 
    // etc., do initialization 

    if(parent != null) 
     parent.add(this); 
    } 

    private void add(Node1 child) { 
    child.setParent(this); 
    children.add(child); 
    } 
} 

Beachten Sie, dass setParent () sollte entweder eine Ausnahme auslösen, wenn das Kind bereits die Elterngruppe hat, oder sich selbst aus der Kindliste der früheren Eltern entfernen.

0

Zuerst die schlechte in Ihrer ersten Probe ist: if (Eltern! = Null) { diese Überprüfung ist notwendig, weil Sie eine Chance Wurzel des Baumes zu schaffen haben sollte, aber mit zwei Zuständen Parameter sieht hässlich aus.

Auch zuerst Ihre Probe nicht gut, weil implizite Aktionen (Hinzufügen von Kind zu übergeben Eltern).

0

Ich würde die Implementierung # 1 nur dann bevorzugen, wenn es absolut notwendig ist, einen Elternknoten mit einem Kindknoten zu haben. In diesem Fall ist es durchaus möglich, dass der Client-Code den Aufruf von Node1.add (Node1 Kind) weglässt und später zu Fehlern führt.

Ich würde Implementierung # 2 ansonsten bevorzugen, weil es klarer ist, eine Nutzung zu haben, wie

Node1 parent = new Node1(); 
Node1 child = new Node1(); 
parent.add(child); 
Verwandte Themen