5

下面的 getCategory 方法似乎非常多余,我想知道是否有人对重构它有一些建议,以使其更清洁,可能使用枚举。根据传入的“val”,我需要 getCategory 从 Category 类返回正确的 Category 实例。Category 类是生成的 JNI 代码,所以我不想更改它。有人有想法么?

重构方法:

private Category getCategory(String val) throws Exception{
        Category category;
        if (val.equalsIgnoreCase("producer")) {
            usageCategory = Category.CATEGORY_PRODUCER;
        } else if (val.equalsIgnoreCase("meter")) {
            usageCategory = Category.CATEGORY_METER;
        } else if (val.equalsIgnoreCase("consumer")) {
            usageCategory = Category.CATEGORY_CONSUMER;
        } else {
            throw new Exception("Invalid value: " + val);
        }       
        return usageCategory;
    }

Category.java:生成的 JNI(无法更改):

public final class Category {
  public final static Category CATEGORY_PRODUCER = new Category("CATEGORY_PRODUCER", SampleJNI.CATEGORY_PRODUCER_get());
  public final static Category CATEGORY_METER = new Category("CATEGORY_METER", SampleJNI.CATEGORY_METER_get());
  public final static Category CATEGORY_CONSUMER = new Category("CATEGORY_CONSUMER", SampleJNI.CATEGORY_CONSUMER_get());

}
4

3 回答 3

6

您的方法本质上是从预定映射String到 a Category,那么为什么不使用 aMap呢?具体来说,我推荐 Guava's ImmutableMap,因为这些映射是静态的:

private static final ImmutableMap<String, Category> CATEGORIES_BY_STRING =
        ImmutableMap.of(
            "producer", Category.CATEGORY_PRODUCER,
            "meter", Category. CATEGORY_METER,
            "consumer", Category.CATEGORY_CONSUMER
        );

或者如果您不想使用第三方库,则使用标准方式:

private static final Map<String, Category> CATEGORIES_BY_STRING;
static {
    Map<String, Category> backingMap = new HashMap<String, Category>();
    backingMap.put("producer", Category.CATEGORY_PRODUCER);
    backingMap.put("meter", Category.CATEGORY_METER);
    backingMap.put("producer", Category.CATEGORY_CONSUMER);
    CATEGORIES_BY_STRING = Collections.unmodifiableMap(backingMap);
}

您仍然可以使用您的方法来检查无效值(并支持不区分大小写,正如 David Harkness 指出的那样):

private Category getCategory(String val) {
    Category category = CATEGORIES_BY_STRING.get(val.toLowerCase());
    if (category == null) {
        throw new IllegalArgumentException();
    }
    return category;
}

关于使用枚举:

如果您可以完全控制String传递给 s 的 s getCategory,并且只会传递文字值,那么切换到 a 确实有意义enum

编辑:以前,我建议EnumMap在这种情况下使用,但阿德里安的回答更有意义。

于 2012-04-05T04:13:38.707 回答
5

如果您说要基于枚举进行重构,我假设您的意思是您不再希望将 String 传递给 getCategory 来完成所有这些工作。该代码直接使用枚举,而不是使用字符串。

如果是这种情况,请继续阅读

幸运的是,您的 Category 是静态变量,因此您可以直接做一些真正的事情

public enum FooCategory {  // give a better name yourself
  PRODUCER(Category.CATEGORY_PRODUCER),
  METER(Category.CATEGORY_METER),
  CONSUMER(Category.CATEGORY_CONSUMER)

  private Category category;
  FooCategory(Category category) {
    this.category=category;
  }
  Category getCategory() {
    return this.category;
  }
}

在您的旧代码中,您正在执行以下操作:

String fooCategory = "producer";
//....
Category category = getCategory(fooCategory);
// work on category

现在你正在做一些更整洁的事情

FooCategory fooCategory = FooCategory.PRODUCER;
//...
Category category = fooCategory.getCategory();
// work on category
于 2012-04-05T04:39:07.093 回答
1

@PaulBellora 和 @AdrianShum 的答案都很棒,但我认为你不能避免使用像“producer”(不区分大小写)这样的魔法值来生产Category存储原因。所以恐怕其中的冗余代码getCategory也无法避免。(不幸的是,用于初始化Category和获取的魔法值Category不一样)

以下是要使用的代码Enum(Java 1.5 或更高版本):

public enum Category {
    CATEGORY_PRODUCER,
    CATEGORY_METER,
    CATEGORY_CONSUMER;

    public static Category of(String val) throws Exception {
        Category usageCategory;
        if (val.equalsIgnoreCase("producer")) {
            usageCategory = Category.CATEGORY_PRODUCER;
        } else if (val.equalsIgnoreCase("meter")) {
            usageCategory = Category.CATEGORY_METER;
        } else if (val.equalsIgnoreCase("consumer")) {
            usageCategory = Category.CATEGORY_CONSUMER;
        } else {
            throw new Exception("Invalid value: " + val);
        }       
        return usageCategory;
    }
}

如果你使用相同的魔法值来生产、获取和存储,你可以:

public enum Category {
    CATEGORY_PRODUCER("producer"),
    CATEGORY_METER("meter"),
    CATEGORY_CONSUMER("consumer");

    private String category;
    private Category(String category) {
        this.category = category;
    }

    public static Category of(String val) throws Exception {
        Category usageCategory;
        // You can use equals not equalsIgnoreCase, so you can use map to avoid redundant code.
        // Because you use the same magic value everywhere.
        if (val.equals("producer")) {
            usageCategory = Category.CATEGORY_PRODUCER;
        } else if (val.equals("meter")) {
            usageCategory = Category.CATEGORY_METER;
        } else if (val.equals("consumer")) {
            usageCategory = Category.CATEGORY_CONSUMER;
        } else {
            throw new Exception("Invalid value: " + val);
        }       
        return usageCategory;
    }
}

并创建一个Category

Category category = Category.of("producer");

当然,您必须更改代码以包含SampleJNI.CATEGORY_CONSUMER_get().

于 2012-04-05T05:31:38.847 回答