通常情況下,如果要比較使用不同屬性的對象 (請參閱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());
}
}
不過,我真的不喜歡這樣的選擇,因爲在這種情況下,我必須提供兩個組件 到客戶端,當比較方法強烈依賴於節點時。
我想我錯過了這個設計中的一些東西。你有什麼想法?
我在另一篇文章中看到了漂亮的枚舉比較器。儘管代碼很優雅,但問題是我必須將值與枚舉內部進行比較,從而導致ScoreNode的可重用性受到影響。 –