2016-03-17 61 views
0

好吧,我一直在努力解決我遇到的這個問題。訪客模式和邏輯操作

我已經創建了具有邏輯節點的樹結構,例如,或者,等於,之間。 我不希望這些節點擁有比訪問者更多的接受方法,因爲會有更多的訪問者使用不同的實現。

因此,例如我正在訪問和。它首先訪問自己,所以我知道我正在處理一個,然後它正在訪問左側和右側節點。它可以是任何較早的節點。

問題是,我需要一種檢查方式來完成訪問子節點。 例如,我想這個輸出

「和(equals()方法/或(的equals()/())之間的」

但已被訪問,因爲我沒有辦法知道,當孩子的這將是成才這樣。

「和()等於()/或()等於()/()之間

就如何克服這個職業有什麼建議blem?

+0

檢查您是否完成訪問子節點?你什麼意思?是不是在'''.accept()'''調用結束時完成了?你是否在異步執行它? –

回答

0

感謝提示jgauffin! 但我按照自己想要的方式得到了更小的工作。

開始使用泛型。

public abstract class Node 
{ 
    public abstract T Accept<T>(IVisitor<T> visitor); 
} 

public interface IVisitor<T> 
{ 
    T Visit(And element); 
    T Visit(Or element); 
    T Visit(Equals element); 
} 

所以我的訪問者可以實現它沒有這樣的對象的任何關注:

public string Visit(Or element) 
{ 
    return "Or(" + element.Left.Accept(this) + "," + element.Right.Accept(this) + ")"; 
} 

所以我的計劃只是被動地接受根節點,將打印出我之前提到的字符串。

+0

歡迎來到Stack Overflow。如果你喜歡@jgauffin的答案,你應該投票和/或接受它。 – Fuhrmanator

0

所以你需要跟蹤節點訪問時你在樹中的位置。爲了能夠做到這一點,你需要引入某種上下文。

事情是這樣的:

public class VisitContext 
{ 
    // Visited node 
    public VisitedType Visited { get; set; } 

    // Visited node is the left child node 
    public bool IsLeftNode { get; set; } 

    // Visited node is the right child node 
    public bool IsRightNode { get; set; } 
} 

所以訪問者得到這個合同:

public interface IVisitor 
{ 
    public void Visit(VisitContext context); 
} 

現在你只需要遍歷它。關鍵是要有一個受保護的超載,告訴孩子他們是哪種類型的。請注意遞歸調用。

public class VisitedType 
{ 
    public void Accept(IVisitor visitor) 
    { 
     var context = new VisitContext{ Visited = this }; 
     visitor.Visit(context); 

     _leftNode.AcceptAsLeft(context); 
     _rightNode.AcceptAsRight(context); 
    } 

    protected void AcceptAsLeft(VisitContext context) 
    { 
     context.IsLeftNode=true; 
     context.IsRightNode=false; 
     visitor.Visit(context); 

     _leftNode.AcceptAsLeft(context); 
     _rightNode.AcceptAsRight(context); 
    } 

    protected void AcceptAsRight(VisitContext context) 
    { 
     context.IsLeftNode=false; 
     context.IsRightNode=true; 
     visitor.Visit(context); 

     _leftNode.AcceptAsLeft(context); 
     _rightNode.AcceptAsRight(context); 
    } 
} 

現在你知道你什麼時候在樹上左右移動,但是你仍然不知道樹在哪裏。要做到這一點,我們來介紹一下跟蹤我們當前路徑的血統/麪包屑。

public class VisitContext 
{ 
    public VisitedType Visited { get; set; } 
    public bool IsLeftNode { get; set; } 
    public bool IsRightNode { get; set; } 

    // this. 
    public LinkedList<VisitedType> Lineage { get; set; }  
} 

而且更新訪問類型:

public class VisitedType 
{ 
    public void Accept(IVisitor visitor) 
    { 
     var context = new VisitContext{ Visited = this, Lineage = new LinkedList<VisitedType>() }; 
     context.Lineage.AddLast(this); 
     visitor.Visit(context); 

     _leftNode.AcceptAsLeft(context); 
     _rightNode.AcceptAsRight(context); 
    } 

    protected void AcceptAsLeft(VisitContext context) 
    { 
     //add a bread crumb 
     context.Lineage.AddLast(this); 
     context.IsLeftNode=true; 
     context.IsRightNode=false; 
     visitor.Visit(context); 

     _leftNode.AcceptAsLeft(context); 
     _rightNode.AcceptAsRight(context); 

     //remove us when we've visited our children 
     context.Lineage.RemoveLast(); 
    } 

    protected void AcceptAsRight(VisitContext context) 
    { 
     //add a bread crumb 
     context.Lineage.AddLast(this); 
     context.IsLeftNode=false; 
     context.IsRightNode=true; 
     visitor.Visit(context); 

     _leftNode.AcceptAsLeft(context); 
     _rightNode.AcceptAsRight(context); 

     //remove us when we've visited our children 
     context.Lineage.RemoveLast(); 
    } 
} 

現在,你應該能夠跟蹤通過層級的訪問。這可以通過遞歸調用來實現,它將在遍歷層次結構時繼續構建麪包屑。