2016-04-27 37 views
2

例如,我有一個用於二叉樹的Node類。添加有關現有對象的其他信息的更好方法是什麼?

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

而現在,我有一個需要記錄一些信息,有關Node實例和只能私下使用他們的處理器。假設預訂樹中的數字遍歷。

我覺得一個直接的方式,使這是在類中添加一個字段:

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

不過,我相信絕對是一個壞主意。所以,我現在使用的是:使用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 
    } 
} 

當然,這可以解決問題。但我擔心的是:

  1. 頻繁訪問地圖似乎效率較低? (與加場方法相比)
  2. 如果我需要更多類型的信息,我需要製作更多的地圖,這似乎是一場噩夢。

那麼,請問有沒有更好的方法?謝謝!

+0

*「不過,我相信這絕對是一個壞主意。」*爲什麼? Node是否在其他處理器中重用? –

+0

@ T.J。Crowder是的,'Node'被廣泛分享。 – abcdabcd987

+4

我想你可以繼承'Node'並添加儘可能多的信息。 – dejvuth

回答

2

最好的解決方案可能是擴展Node對象,這將允許您利用新功能,同時不會破壞現有代碼。

您也可以將它與DecoratorFactory模式耦合起來,嘗試使用透明的結構化對象創建過程。

0

這是一個問題分離的問題。您想要添加節點或樹處理器的關注信息。

我會說,下面的語句描述的情況

  • 樹有節點(成分聚合)
  • 節點具有節點(聚集)
  • 節點具有節點信息(彙總)
  • 處理器處理的樹(依賴)

所以我會把或信息與節點關聯。爲了有一定程度的flexbility的,你可能會對節點

class ExtNode extends Node { 

    int no; 

} 

的延伸或裝飾的信息:

class NodeDecorator { 

    Node node; 
    int no; 

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

如果你去的地圖,效率不應該在這個階段成爲你的關注點。訪問地圖非常有效。如果需要,可以稍後進行優化。

如果添加了附加信息,您可以定義一個新結構,比如NodeInfo,並將所有信息放在那裏,並將其放入Map或節點而不是int。

例如

class NodeInfo { 
    int no; 
    String other; 
} 
0

附加信息是特定於節點的層次結構中的一個處理器,因此它不應該泄漏到節點(關注點分離)

潛在的解決方案:

  1. 對此處理器使用並行樹結構

由於Node是樹結構,因此使用在訪問Node結構時構建的並行結構。這個並行項目(ProcessedNode?)將包含附加信息,對節點的引用以及左/右ProcessedNode子項。

這可能在內存和訪問(無地圖開銷)方面更好,但會使處理器更復雜一點:它會訪問ProcessedNode而不是Node。它不會訪問下一個節點,而是爲下一個節點創建一個ProcessedNode,並訪問ProcessedNode。

您可以延遲構建ProcessedNode,因此並行樹是根據需要構建的。

如果節點樹可能發生變異,並且您需要保留ProcessedNode信息的時間超過一次處理的持續時間,這是不實際的。

  • 使用地圖
  • 代替具有每附加信息的一個映射,可以收集所有這些在含有附加信息的類細節,並且使用單一的地圖

    該解決方案的優點是實施簡單。 缺點是如果你保留地圖,你需要維護一個節點是否消失。

    最終的選擇取決於需要多長時間的額外細節,如果您只需要在處理期間維護信息,那麼地圖將在處理結束時被丟棄,因此添加的成本項目到地圖沒有槓桿。

    如果創建地圖是實用的,那麼在使用備用解決方案進行優化之前,您應該測量什麼是實際開銷:是否值得付出努力?

    0

    對於子分類方法,您應該使用「getter方法」來訪問子節點,以便子類可以覆蓋它們。

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

    並在一個子類中重寫這些,在需要時延遲創建子節點。

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

    然後將new DecoratedNode(root)傳遞給處理方法。

    相關問題