2009-03-10 12 views
7

Pracuję z kodem, który dodaje węzeł podrzędny do rodzica w konstruktorze dziecka. Kod wygląda mniej więcej tak:Najlepsza praktyka: Dodawanie węzła potomnego do obiektu nadrzędnego w konstruktorze podrzędnym, czy nie?

Klasa:

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

Zastosowanie:

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

Poprzez wdrożenie go w ten sposób użytkownikowi klasy Node1 nie trzeba jawnie dodać węzeł podrzędny (mniej kodu) do rodzica i masz gwarancję, że węzeł podrzędny ma rodzica.

Ja osobiście nie napisałby to w ten sposób, ale bardziej jak następuje:

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

Więc moje pytanie brzmi, czy jest to dobry pomysł, aby go realizować w sposób pokazany w klasie Node1 czy są jakieś sprzeciwy, aby zrobić to w ten sposób? Czy też nie ma argumentu, dlaczego jeden jest lepszy od drugiego?

Odpowiedz

11

Osobiście nie podoba mi się pierwszy przykład, ponieważ dodajesz węzeł, który nie jest jeszcze "gotowy" (ponieważ konstruktor nie zakończył wykonywania). W większości przypadków będzie działało dobrze, ale w skrajnych przypadkach możesz mieć błędy, które są dość trudne do znalezienia.

+0

+1: Prawie co bym powiedział. –

+0

To jest dobra uwaga, lepiej nie używać tego w konstruktorze. –

1

Myślę, że obie implementacje są w porządku.

Pytanie brzmi raczej, jak użyjesz tej klasy: czy najpierw utworzysz listę węzłów, a następnie zaczniesz dodawać ich relacje, czy zrobisz to w uporządkowany sposób, jak w twoim przykładzie?

Drugie rozwiązanie oferuje więcej elastyczności, również jeśli chcesz używać Node1 jako superklasy, nie jesteś związany z sygnaturą konstruktora.

2

Używałbym drugiego przypadku, ponieważ wtedy będę mógł dodać dzieci później, ale nie tylko w konstruktorze.

0

Jeśli wyprowadzisz węzeł z klasy TreeNode, automatycznie otrzymasz drugą implementację. Możesz dodać swój "niestandardowy" treenode do zwykłej klasy Treeview.

1

Nie podoba mi się pierwszy przypadek - obiekt nadrzędny jest magicznie modyfikowany przez samo przekazanie - musisz przeczytać kod lub dokumenty, aby zdać sobie sprawę, że tak się dzieje. Przekazywanie tylko rodzicowi oznacza, że ​​dziecko zna rodzica - nie, że dziecko jest również dodawane do wewnętrznej listy rodzica.

Drugi przykład jest lepszy. Można również zwrócić dziecku z operacji „Dodaj”, aby umożliwić działanie łańcuchowym jak:

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

nie widzę powodu, dlaczego nie połączyć tych dwóch podejść dla wygody:

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

Zauważ, że setParent () powinien albo rzucić wyjątek, gdy dziecko ma już swój zestaw rodziców, albo właściwie usunąć się z listy dzieci byłego rodzica.

0

Po pierwsze źle w pierwszej próbce jest: if (rodzic! = Null) { konieczna jest ten czek, bo trzeba mieć szansę na stworzenie korzeń drzewa, ale dwa-state parametr wygląda brzydko.

Również pierwsza próbka nie jest dobra, ponieważ wykonuje niejawne działania (dodawanie dziecka do przekazanego rodzica).

0

Wolałbym wdrożenie nr 1 tylko wtedy, gdy bezwzględnie konieczne jest posiadanie węzła nadrzędnego z węzłem podrzędnym. W takim przypadku kod klienta może całkowicie pominąć wywołanie funkcji Node1.add (węzeł Node1), co prowadzi do błędów w późniejszym czasie.

wolałbym wdrażania nr 2 inaczej, ponieważ jest jaśniejsza mieć wykorzystanie podobnego

Node1 parent = new Node1(); 
Node1 child = new Node1(); 
parent.add(child); 
Powiązane problemy