下面的getCategory方法似乎非常多余,我想知道是否有人有一些关于重构它的建议,以使其更清洁可能使用Enum。基于" 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());
}
答案 0 :(得分:6)
您的方法基本上是映射从预定的String
到Category
,那么为什么不使用Map
呢?具体来说,我推荐Guava的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
的{{1}},并且只传递文字值,那么切换到getCategory
会有意义。
编辑:以前,我建议在这种情况下使用EnumMap
,但Adrian's answer更有意义。
答案 1 :(得分:5)
如果你说要基于枚举进行重构,我认为你的意思是你不再希望传递String到getCategory来完成所有这些工作。代码直接使用枚举,而不是使用String。
如果是这种情况,请继续阅读
幸运的是,你的类别是静态变量,所以你可以做一些真正直接的事情
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
答案 2 :(得分:1)
@PaulBellora和@AdrianShum的答案都很棒,但我认为你不能避免使用魔术值,就像'生产者'(不区分大小写)一样,出于存储原因而生成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()
。