我首先假设您确实需要枚举常量来建模这个用例,因为您有某种特定的代码要为每种血液测试执行(否则,一组简单的字符串就足够了,而且更灵活,因为您不需要预先知道测试的数量或关心他们的名字)。
Q1:由于 Java 枚举不仅仅是一个值序列,因此您可以充分利用其面向对象的特性。
public enum BloodTest {
AAA, BBB, CCC;
private static String[] names;
public static void setNames(String[] names) {
if (BloodTest.names != null)
throw new IllegalStateException("You can only set the names once");
if (names.length != values().length)
throw new IllegalArgumentException("Wrong number of names");
BloodTest.names = names;
}
@Override
public String toString() {
return names[ordinal()];
}
}
现在你需要做的就是通过调用来初始化你的枚举BloodTest.setNames(namesFromConfiguration)
,然后你可以通过调用它的标准toString()
方法来获取每个常量的字符串表示:BloodTest.BBB.toString()
.
由于最初的假设是您对每种测试类型都有一些特定的逻辑,因此我建议逻辑(以及所需的属性)也将封装在枚举本身或枚举常量中;例如:
public enum BloodTest {
AAA(10) {
@Override
public boolean isRequired(MedicalRecord medicalRecord) {
return medicalRecord.includes("someDisease");
}
},
BBB(15) {
@Override
public boolean isRequired(MedicalRecord medicalRecord) {
return ! medicalRecord.hasTakenBloodTestsLately();
}
},
CCC(20) { // ... also implements the abstract method and so on
private final int threshold;
private BloodTest(int threshold) {
this.threshold = threshold;
}
public boolean hasPassed(int value) {
return value <= threshold;
}
public abstract boolean isRequired(MedicalRecord medicalRecord);
// ... same as above
}
现在,一旦您获得对 some 的引用BloodTest
,您就可以通过调用相应的方法而不使用switch
ing 并让逻辑在客户端代码周围传播来检查该特定测试是否通过:
BloodTest bloodTest = BloodTest.valueOf(someString); // someString can be "AAA", "BBB" or "CCC"
// no matter which constant this is, you use it as an object and rely on polymorphism
if (bloodTest.hasPassed(someValue)) { // ... do something
Q2:您的问题 2 是我对您实际需要枚举的初步假设。如果您有可能需要动态处理您还不知道的血液测试,那么您不能使用枚举。
换句话说,如果您的代码没有任何switch
或if/else if
块来处理每次血液测试,那么枚举对于您的用例来说是一个非常糟糕的选择。
但是,如果确实如此,那么我建议重构代码以将逻辑包含在枚举本身中,就像上面的示例一样,而不是switch
/if
块;此外,如果你switch
有一个default
案例(或者你if
有一个最终else
块),这仍然可以在枚举本身中建模,例如通过添加一个DEFAULT
常量作为后备。