根据选定的枚举值调用对象的特定方法

Call specific method on object depending on selected enum value

假设我们有一个代表可搜索字段的枚举:

enum SearchableFields {
    ALL,
    FIELD1,
    FIELD2,
    FIELD3;
}

此枚举通过 GUI 内的(组合框)选择显示。在运行时,我想评估这个组合框的选择并进行相应的搜索。

根据选择,我需要通过 getter.

从 POJO(下面的示例)中检索要搜索的字段
class FieldPojo {
    private String field1;
    private String field2;
    private String field3;
    ...
    public String getField1() {
        return field1;
    }
    ...
}

我目前使用 switch 语句来评估 SelectableFields 的选择,然后检索要搜索的正确字段:

private String retrieveField(FieldPojo f) {
    switch (selectedField) {
    case ALL:
        return retrieveAll(); // method that retrieves all available fields
    case FIELD1:
        return f.getField1();
    ...
}

这确实有效,但我觉得它很笨重。

问题:

有没有更简洁的方法来做到这一点而无需通过 switch 评估 enum? (Java 8)

枚举可以包含方法定义,因此一种方法是根据枚举值定义检索字段名的方法。我假设您也将实际字段名称存储为成员字段。然后你可以覆盖特殊 ALL 值的方法:

enum SearchableFields {
    ALL("all") { // all is just a placeholder in this case
        @Override
        String retrieveField(FieldPojo f) {
            // logic for all fields
        }
    },
    FIELD1("field1"),
    FIELD2("field2"),
    FIELD3("field3");
    
    SearchableFields(String fieldName) {
        this.fieldName = Optional.of(fieldName);
    }
    SearchableFields() {
        fieldName = Optional.empty();
    }
    private final Optional<String> fieldName;

    String retrieveField(FieldPojo f) {
        if (fieldName.isPresent()) {
            return (String) f.getClass().getField(fieldName.get()).get(f);
        } else {
           // ...
        }
    }
}

您可以创建静态地图而不是 switch-case。

private static final Map<SearchableFields,Supplier<String>> searchableFieldsToFieldPojo = Map.of(
    ALL, this::retrieveAll,
    FIELD1, FieldPojo::retrieveAll
    );

然后您可以通过以下方式访问:

searchableFieldsToFieldPojo.get(selectedField).get();

鉴于您可以修改代码的所有部分,您有多种选择:

  • retrieveField 放入 class FieldPojo 并修改其参数,使其以枚举 SearchableFields 作为参数。
  • FieldPojo 的字段作为值放入具有类型 SearchableFields 键的映射中。然后您可以决定是否要将“ALL”作为映射的额外条目,或者在类似于 retrieveField 的方法中将其作为特殊情况处理。如果你想更新枚举而不是 FieldPojo class.
  • ,你可以使用它来进行“默认”处理
  • 您将 retrieveFieldSearchableFields 枚举一起放入 class FieldPojo - 因为只有 FieldPojo 知道,它实际提供哪些字段可搜索字段。
  • 您使用内省来收集可能的可搜索字段列表并访问它们的内容。

根据您的实际要求(您只展示了它们的非常抽象和具体的版本),一种或另一种方法可能是适合您的“正确方法”。我实际上更喜欢“一切都变成 FieldPojo”作为最强大的,但另一方面,如果你不能改变 FieldPojo 并且必须处理许多不同的 classes它,内省变体可能是正确的。 (请注意,它在安全方面很脆弱,而且可能非常慢。)

您可以在枚举常量中存储对 getter 的引用:

enum SearchableFields {
    ALL(FieldPojo::retrieveAll),
    FIELD1(FieldPojo::getField1)

    private final Function<FieldPojo, String> accessor;
    SearchableFields(Function<FieldPojo, String> acccessor) {
        this.accessor = accessor;
    }

    public String get(FieldPojo fp) {
        return accessor.apply(fp);
    }
}