2013-04-15 86 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的可重用性受到影响。 –