[英]Java Method Refactoring Using Enum
下面的 getCategory 方法似乎非常多余,我想知道是否有人对重构它有一些建议,可以使用枚举使其更干净。 基于传入的“val”,我需要 getCategory 从类别 class 返回正确的类别实例。类别 class 是生成的 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());
}
您的方法本质上是从预定的String
映射到Category
,那么为什么不使用Map
呢? 具体来说,我推荐 Guava 的ImmutableMap
,因为这些映射是 static:
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;
}
关于使用枚举:
如果您可以完全控制传递到getCategory
的String
,并且只会传递文字值,那么切换到enum
确实有意义。
编辑:以前,我建议在这种情况下使用EnumMap
,但Adrian 的回答更有意义。
如果你说你想基于枚举进行重构,我假设你的意思是你不再想将 String 传递给 getCategory 来完成所有这些工作。 代码直接使用枚举,而不是使用字符串。
如果是这种情况,请继续阅读
幸运的是,您的类别是 static 个变量,因此您可以直接做一些真正的事情
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
@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()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.