【问题标题】:Passing argument to enum abstract method将参数传递给枚举抽象方法
【发布时间】:2019-12-29 11:09:34
【问题描述】:

我需要提供一个搜索属性工厂(作为 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 新?
  • 只有 8 个(不允许在本练习中使用更新版本)
  • 没关系,8个就够了。
  • compare 方法是如何使用的?你打算如何传递布尔值?
  • 比较方法用于我实现的自定义排序。我不知道如何传递布尔值,这是我的问题。

标签: java oop enums factory


【解决方案1】:

从 Java 8 开始,java.util.Comparator<T> 有一个可以使用的默认方法 reversed()

您可以让您的enum 实现Comparator,然后您“免费”获得反向排序,但这意味着更改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;
  }
}

那么,当你使用类实例时:

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&lt;T&gt; 中获得的其他内容,尽管其中大部分可能对您没有多大用处。

您也可以考虑将其作为一个整体进行重构,因此您的 CompareChoice 可能不是“真正的”比较器,而是返回一个比较器。这样您就可以通过比较器实现更好地分离关注点:

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();
}

【讨论】:

  • 注意:我的解决方案不仅需要更改compare 方法的返回类型,而且还需要在CompareChoice 上调用reversed() 不会产生CompareChoice 实例,所以这样的调用不能被束缚。总而言之,我更喜欢这里的comparator() 方法。
猜你喜欢
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多