2013-04-15 130 views
2

通常情況下,如果要比較使用不同屬性的對象 (請參閱How to compare objects by multiple fields),比較器是最佳選擇。 但是,在我的具體情況下,我不確定使用比較器。通過不使用比較器的不同屬性比較對象

問題是:我定義了一個通用接口,稱爲Node<S>,它由不同的組件共享 。還有一個CostNode<S>延伸的Node<S>ScoreNode<S> 延伸CostNode<S>

public interface Node<S> { 
    S getS(); 
    // more methods... 
} 

public interface CostNode<S> extends Node<S> { 
    // This method smells really bad 
    int compareByCost(ComparableNode<S> node); 
} 

public interface ScoreNode<S> extends CostNode<S> { 
    // int compareByCost(CostNode<S> node) (from CostNode<S>) 
    int compareByScore(ScoreNode<S> node); 
} 

在這一點上,有人可以說:你不需要CostNode和ScoreNode,你 可以使用不同的比較來比較節點。沒關係。但「問題」現在來:

我有一個組件,稱爲客戶端,它使用ScoreNodes。客戶需要一個節點工廠, 用戶,負責創建ScoreNodes提供:

public class Client { 
    // ... 

    public Client(NodeFactory<S, ScoreNode<S>> nodeFactory){...} 

    public void process() { 

     while(...){ 
      S current = get(); 
      S old = getOld(); 
      // ... 
      ScoreNode<S> next = this.nodeFactory.create(current,...)); 
      // Comparisons performed 
      if (next.compareByCost(old) <=0){ 
       //... 
      } 
      if (next.compareByScore(old) > 0){ 
       // ... 
      } 
     } 

    } 
} 

正如你所看到的,比較節點的行爲被嵌入到節點, 密切相關工廠使用(不同的節點需要不同的工廠 和不同的比較器)。另一方面,如果我使用比較器,我必須向客戶提供三個組件: CostComparator,ScoreComparator和NodeFactory。在這種情況下,我只能使用Node<S> 而忘記了CostNode<S>ScoreNode<S>

public class ConcreteNodeCostComparator implements Comparator<Node<S>> { 
    public int compare(Node<S> a, Node<S> b){ 
     return Double.compare(((ConcreteNode<S>)a).getCost(), ((ConcreteNode<S>)b).getCost()); 
    } 
} 

public class ConcreteNodeScoreComparator implements Comparator<Node<S>> { 
    public int compare(Node<S> a, Node<S> b){ 
     return Double.compare(((ConcreteNode<S>)a).getScore(), ((ConcreteNode<S>)b).getScore()); 
    } 
} 

不過,我真的不喜歡這樣的選擇,因爲在這種情況下,我必須提供兩個組件 到客戶端,當比較方法強烈依賴於節點時。

我想我錯過了這個設計中的一些東西。你有什麼想法?

回答

1

你應該看看Boune的回答。 (http://tobega.blogspot.fr/2008/05/beautiful-enums.html

你可以使用那種枚舉在ScoreNode接口(或其他地方),並使用:

ScoreNode.Order.ByCost.compare(node1, node2); 
ScoreNode.Order.ByScore.compare(node1, node2); 

您沒有提供任何更多的部件到客戶端。

+0

我在另一篇文章中看到了漂亮的枚舉比較器。儘管代碼很優雅,但問題是我必須將值與枚舉內部進行比較,從而導致ScoreNode的可重用性受到影響。 –