Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不使用比较器,通过不同属性比较对象_Java_Oop_Compare_Design Patterns - Fatal编程技术网

Java 不使用比较器,通过不同属性比较对象

Java 不使用比较器,通过不同属性比较对象,java,oop,compare,design-patterns,Java,Oop,Compare,Design Patterns,通常,当您想要比较使用不同属性的对象时,比较器是最佳选择 (参见示例)。 然而,在我的特殊情况下,我不确定是否使用比较器 问题如下:我定义了一个通用接口,名为节点,它是共享的 由不同的组成部分组成。还有一个扩展节点的CostNode,以及一个ScoreNode 它扩展了成本节点: 公共接口节点{ S get(); //更多方法。。。 } 公共接口CostNode扩展节点{ //这种方法闻起来很难闻 int compareByCost(可比节点); } 公共接口ScoreNode扩展了CostNo

通常,当您想要比较使用不同属性的对象时,比较器是最佳选择 (参见示例)。 然而,在我的特殊情况下,我不确定是否使用比较器

问题如下:我定义了一个通用接口,名为
节点
,它是共享的 由不同的组成部分组成。还有一个扩展
节点的
CostNode
,以及一个
ScoreNode
它扩展了成本节点

公共接口节点{
S get();
//更多方法。。。
}
公共接口CostNode扩展节点{
//这种方法闻起来很难闻
int compareByCost(可比节点);
}
公共接口ScoreNode扩展了CostNode{
//int compareByCost(CostNode节点)(来自CostNode)
int compareByScore(ScoreNode节点);
}
在这一点上,有人会争论:你不需要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){
               // ...
            }
        }

    }   
}
公共类客户端{
// ...
公共客户端(NodeFactory NodeFactory){…}
公共程序(){
而(…){
S current=get();
S old=getOld();
// ...
ScoreNode next=this.nodeFactory.create(当前,…);
//进行的比较
if(next.compareByCost(旧)0){
// ...
}
}
}   
}
如您所见,比较节点的行为嵌入到节点中,并且 与所使用的工厂密切相关(不同的节点需要不同的工厂 和不同的比较器)

另一方面,如果我使用比较器,我必须向客户提供三个组件: CostComparator、ScoreComparator和NodeFactory。在这个场景中,我只能使用
节点
忘记
CostNode
ScoreNode

公共类ConcreteNodeCostComparator实现Comparator{
公共整数比较(节点a、节点b){
返回Double.compare((ConcreteNode)a.getCost(),((ConcreteNode)b.getCost());
}
}
公共类ConcreteNodeScoreComparator实现Comparator{
公共整数比较(节点a、节点b){
返回Double.compare((ConcreteNode)a.getScore(),((ConcreteNode)b.getScore());
}
}
然而,我并不真的喜欢这个替代方案,因为在这种情况下,我必须再提供两个组件 对于客户端,当比较方法强烈依赖于节点时


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

你应该看看你链接的帖子中Boune的答案。 ()

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


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

我在另一篇文章中看到了漂亮的enum comparator。虽然代码很优雅,但问题是我必须将要与之比较的值放在枚举中,这会破坏ScoreNode的可重用性。
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){
               // ...
            }
        }

    }   
}
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()); 
    }
}
ScoreNode.Order.ByCost.compare(node1, node2);
ScoreNode.Order.ByScore.compare(node1, node2);