2011-12-27 44 views
0

我想使用訪問者模式來實現樹。所以我做了一個主類Node和擴展該類的其他類(例如Node1Node2Node3)。在Node我有一個字符串和ArrayListNodes這是該節點的子項列表。所以,我實現了一個訪客有3個功能visit(Node1 x),...在main我想打電話給接受每節點:訪問者模式接受不識別對象的類

SomeVisitor v = new SomeVisitor(); 
Node n = makeTree(); 
Iterator<? extends Node> it = n.children.iterator(); 
while(it.hasNext()) { 
    System.out.println(it.next().getClass()); 

    it.next.accept(v); 
} 

這不起作用,因爲即使.getClass返回特定類 我的意思是,節點1 ,2或3,我得到的錯誤是it.next是 型節點,但我沒有在我的樹的任何節點對象,我並沒有實現 visit(Node)只是visit(Node 1,2,3)

+0

你必須在你的發佈代碼位的錯誤:你調用'it.next ()'在同一次迭代中兩次。 – toto2 2011-12-27 16:02:12

回答

0

你的解決方案是使用訪客模式,這不是你看起來正在做的事情。

我並沒有實現訪問(節點)只需訪問(節點1,2,3)

這是你的問題。你必須用你所說的相同的方法實現相同的接口。

你也需要把它寫成

v.visit(it.next()); 

@JB Nizet的解決方案是相似的,但我認爲它更簡單寫在它需要從一開始就被稱爲方式的代碼。

+0

沒有。 accept方法應該在基類節點類中。但是每種類型的子類都應該有一個訪問方法。不需要訪問(Node),除非有幾個子類需要以通用的方式訪問。 – 2011-12-27 16:02:27

+0

因爲每個子類都重寫accept方法。查看我的答案和維基百科鏈接。訪問方法甚至可以有不同的名稱:visitNode1,visitNode2,visitNode3。當訪問者要求接受訪問時,每個子類都決定調用哪種訪問方法。 – 2011-12-27 16:04:49

+0

這並沒有打破多態的整個觀點。爲什麼在正確構造調用時編寫單獨的方法可以避免需要執行此操作? – 2011-12-27 16:09:00

0

很難猜測問題出在哪裏。你應該看看wikipedia這個樣例實現。正如你將會看到那裏的模式不是通過使用擴展來實現的,而是通過使用裝飾接口來實現的。

+0

雖然我不必在Node類中實現接受函數,因爲我沒有使用它來擴展它的類...我會嘗試爲Node實現它,但是我擔心只有這個訪客將被稱爲我的意思是訪問(Node1 2 3)永遠不會被稱爲...我很困惑...我知道訪客模式的作用,但我不能完全理解它..謝謝你的答案! – exilonX 2011-12-27 17:20:01

+0

@IonelMerca:其實你可能不需要'Node'超類。只要讓'Node1','Node2'和'Node3'實現具有'accept(SomeVisitor)'方法的'VisitableNode'接口。 'SomeVisitor'必須有'訪問(Node1)','訪問(Node2)'和'訪問(Node3)'' – Kai 2011-12-27 17:40:46

2

檢查visitor pattern的說明。 accept方法應該在基類中聲明,每個子類都應該通過回調適當的訪問方法來覆蓋它:

public abstract class Node { 
    public abstract void accept(Visitor v); 
} 

public class Node1 extends Node { 
    @Override 
    public void accept(Visitor v) { 
     v.visit(this); // calls visit(Node1) 
    } 
}