java - 在不使用比较器的情况下按不同属性比较对象

标签 java oop compare design-patterns

通常情况下,当你想比较使用不同属性的对象时,比较器是最好的选择 (例如参见 How to compare objects by multiple fields )。 但是,在我的特定情况下,我不确定是否使用比较器。

问题如下:我定义了一个通用接口(interface),称为 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,你 可以使用不同的比较器来比较节点。没关系。但是现在“问题”来了:

我有一个名为 Client 的组件,它使用 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()); 
    }
}

但是,我不太喜欢这个替代方案,因为在这种情况下我必须再提供两个组件 到客户端,当比较方法强烈依赖于节点时。

我想我在这个设计中遗漏了一些东西。你怎么看?

最佳答案

您应该在链接的线程中查看 Boune 的回答。 ( http://tobega.blogspot.fr/2008/05/beautiful-enums.html )

您可以在 ScoreNode 界面(或其他地方)中使用这种枚举并使用:

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

您不必向您的客户提供更多组件。

关于java - 在不使用比较器的情况下按不同属性比较对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16010901/

相关文章:

java - while 循环的问题

java - 当数据不断出现时如何使用 jfreechart 绘制图表

java - 运行单元测试时读取不同属性集的正确方法是什么

javascript - OOP 方法中是否可以知道 ajax 调用何时完成

excel - 匹配 2 列和第三列的结果

c# - 检查多个 boolean 值是否具有相同的值

java - 导航到不同页面并返回后,我收到 StaleElementReferenceException

c++ - Tinyxml 多任务

c++ - 我如何掌握纯 OOD 的概念?

javascript - 如何在 JavaScript 中比较日期