将参数传递给枚举抽象方法

Passing argument to enum abstract method

我需要提供一个搜索属性工厂(作为 Strategy OOP 原则的一部分)。 我为选项编写了以下枚举:

    public enum CompareChoice {
    ABS {
        public Path compare(Path path1, Path path2) {
            return absCompare(path1, path2);
        }
    },

    TYPE {
        public Path compare(Path path1, Path path2) {
            String type1 = getFileType(path1);
            String type2 = getFileType(path2);
            int compareValue = type1.compareTo(type2);
            if (compareValue == 0) {
                return absCompare(path1, path2);
            }

            if (compareValue > 0) {
                return path1;
            }

            return path2;
        }

    },

    SIZE {
        public Path compare(Path path1, Path path2) throws IOException {
            Long size1 = Files.size(path1);
            Long size2 = Files.size(path2);
            int compareValue = size1.compareTo(size2);
            if (compareValue == 0) {
                return absCompare(path1, path2);
            }

            if (compareValue > 0) {
                return path1;
            }

            return path2;
        }
    };

    public abstract Path compare(Path path1, Path path2) throws IOException;
}

我面临的问题是我需要支持反向排序(所有三种选择)。 我想以某种方式将 boolean 参数传递给 compare 的这些实现,但我不知道如何。 关于如何通过仍然使用 enum 很好地实现这一点的任何想法都会非常有帮助!

因为 Java 8,java.util.Comparator<T> 有一个默认方法 reversed() 可以使用。

你可以让你的 enum 实现 Comparator,然后你得到反向排序 "for free",但这意味着改变 compare 的签名以适应 Comparator ] 合同(您需要为该方法考虑另一个名称,在我的示例中,我将其命名为 select;

只取一个枚举值以保持简短:

public enum CompareChoice implements Comparator<Path> {

  SIZE {
    @Override
    public int compare(Path path1, Path path2) {
      int r = Long.compare(
        Files.size(path1),
        Files.size(path2)
      );
      if (r == 0) {
        return absCompare(path1, path2);
      }
      else {
        return r;
      }
    }
  };

  // rest of the methods:
  public static Path select(Comparator<? super Path> rule, Path path1, Path path2) {
    return rule.compare(path1, path2) <= 0 ? path1 : path2;
  }
}

那么,当您使用 class 实例时:

CompareChoice choice = CompareChoice.SIZE;

Path path1 = fileOfSize(1, TB);
Path path2 = fileOfSize(3, TB);

Path naturalOrderResult = CompareChoice.select(choice, path1, path2);
Path reversedOrderResult = CompareChoice.select(choice.reversed(), path1, path2);

assert path1 == naturalOrderResult;
assert path2 == reversedOrderResult;

您可以查看比较器中的其他默认方法,以检查您还可以从实施 Comparator<T> 中获得的其他内容,尽管其中大部分可能对您没有多大用处。

您也可以考虑将其作为一个整体进行重构,因此您的 CompareChoice 可能不是 "true" 比较器,而是 returns 比较器。这样你就可以更好地分离比较器实现的关注点:

public enum CompareChoice {
  ABS {
    public Comparator<? extends Path> comparator() {
      return Comparator.comparing(this::absCompare); // whatever absCompare means
    }
  },

  SIZE {
    public Comparator<? extends Path> comparator() {
      return Comparator.comparingLong(Files::size).thenComparing(ABS.comparator());
    }
  };


  public abstract Comparator<? extends Path> comparator();
}