模仿可扩展枚举行为的综合正确方法是什么?
What'd be the synthetically correct way of imitating extendable enum behavior?
传统上,当我有一个枚举时:
public enum SomeEnum implements Serializable {
TYPE_1,
TYPE_2;
}
或 class:
public class Country {
public static final Country SOME_COUNTRY = new Country("someCode");
private final String code;
...
}
在控制器中,我return这些值来填充一些选择:
@RestController(...)
public List<Field> getFields() {
return Arrays.asList(SomeEnum.class.getEnumConstants());
// or
return Arrays.asList(Country.class.getDeclaredFields());
}
目前,我正在开发一个可以由某些最终产品导入的 webhook 库。一些事件名称来自库本身,但其中一些不存在于库中(但在最终产品代码中):
Webhook
class 看起来像这样:
public class Webhook {
private String url;
private List<WebhookEvent> events;
...
}
和WebhookEvent
如下:
public class WebhookEvent Serializable {
private long id;
private String name;
...
}
和 WebhookEvent
是从数据库中填充的。我 不想 在最终产品中创建控股 class,例如:
public class EnabledEvent {
public static final WebhookEvent SOME_EVENT = new WebhookEvent("event.name");
...
}
因为那会从两个不同的点控制应用程序的行为。但是相反,我希望能够在数据库中有新条目时立即 return 这些 constants/fields。基本上我希望能够根据数据库中的条目模仿扩展 constants/enums 的行为。是否有以编程方式实现此目的的正确方法?
在我们的案例中,有许多常量需要验证。这个常量文件开始堆积。因此,我们不得不设计一种不同的方法,最终只为常量创建了一个单独的 table,这样您就可以添加或 remove/disable 不需要的一次,而无需重新编译您的代码(尽管您必须,如果有依赖案例)。
例如,假设您具有以下患者状态 (STATUS):
稳定、危急、死亡、恢复和 NA
以及 TEST_RESULT 的以下状态:
TEST_PENDING、TEST_NEGATIVE 和 TEST_POSITIVE
table 看起来像:
------------------------------------------------------------------------
enum_code enum_type enum_name enum_desc disabled
------------------------------------------------------------------------
001 STATUS STABLE false
002 STATUS CRITICAL false
003 STATUS DECEASED false
004 STATUS RECOVERED false
005 STATUS NA false
100 TEST_RESULT TEST_PENDING false
101 TEST_RESULT TEST_NEGATIVE false
102 TEST_RESULT TEST_POSITIVE false
------------------------------------------------------------------------
@Entity
@Table(name="constant_enum")
public class ConstantEnum implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="enum_code")
private Integer enumCode;
private boolean disabled;
@Column(name="enum_desc")
private String enumDesc;
@Column(name="enum_name")
private String enumName;
@Column(name="enum_type") // this is the discriminator
private String enumType;
//getters and setters
}
我最终删除了与数据库的连接,并在 class 本身中定义了静态变量,使用静态 ofValue
方法创建对象:
public class SomeClass implements Serializable {
public static final SomeClass MY_CONSTANT_1 = new SomeClass("static.value");
public static SomeClass [] values = new SomeClass []{
SomeClass .MY_CONSTANT_1,
...
};
private String name;
public SomeClass (String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static SomeClass ofValue(String name){
if(StringUtils.isEmpty(name)) return null;
for(SomeClass value : values) if(value .getName().equalsIgnoreCase(name)) return event;
throw new IllegalArgumentException(String.format("Couldn't convert value : %s into a valid %s object", name, SomeClass.class.getName()));
}
}
这样扩展如下:
public class ExtendedSomeClass extends SomeClass implements Serializable {
public static final SomeClass MY_CONSTANT_2 = new SomeClass ("static.value.2");
public static SomeClass[] values = new SomeClass[]{
SomeClass.MY_CONSTANT_2,
};
public static SomeClass ofValue(String name){
if(StringUtils.isEmpty(name)) return null;
for(SomeClass event : values) if(event.getName().equalsIgnoreCase(name)) return event;
return SomeClass.ofEvent(name);
}
}
而且我总是可以从 @RestController
端点连接 values
数组和 return 它来填充表单。
传统上,当我有一个枚举时:
public enum SomeEnum implements Serializable {
TYPE_1,
TYPE_2;
}
或 class:
public class Country {
public static final Country SOME_COUNTRY = new Country("someCode");
private final String code;
...
}
在控制器中,我return这些值来填充一些选择:
@RestController(...)
public List<Field> getFields() {
return Arrays.asList(SomeEnum.class.getEnumConstants());
// or
return Arrays.asList(Country.class.getDeclaredFields());
}
目前,我正在开发一个可以由某些最终产品导入的 webhook 库。一些事件名称来自库本身,但其中一些不存在于库中(但在最终产品代码中):
Webhook
class 看起来像这样:
public class Webhook {
private String url;
private List<WebhookEvent> events;
...
}
和WebhookEvent
如下:
public class WebhookEvent Serializable {
private long id;
private String name;
...
}
和 WebhookEvent
是从数据库中填充的。我 不想 在最终产品中创建控股 class,例如:
public class EnabledEvent {
public static final WebhookEvent SOME_EVENT = new WebhookEvent("event.name");
...
}
因为那会从两个不同的点控制应用程序的行为。但是相反,我希望能够在数据库中有新条目时立即 return 这些 constants/fields。基本上我希望能够根据数据库中的条目模仿扩展 constants/enums 的行为。是否有以编程方式实现此目的的正确方法?
在我们的案例中,有许多常量需要验证。这个常量文件开始堆积。因此,我们不得不设计一种不同的方法,最终只为常量创建了一个单独的 table,这样您就可以添加或 remove/disable 不需要的一次,而无需重新编译您的代码(尽管您必须,如果有依赖案例)。
例如,假设您具有以下患者状态 (STATUS):
稳定、危急、死亡、恢复和 NA
以及 TEST_RESULT 的以下状态:
TEST_PENDING、TEST_NEGATIVE 和 TEST_POSITIVE
table 看起来像:
------------------------------------------------------------------------
enum_code enum_type enum_name enum_desc disabled
------------------------------------------------------------------------
001 STATUS STABLE false
002 STATUS CRITICAL false
003 STATUS DECEASED false
004 STATUS RECOVERED false
005 STATUS NA false
100 TEST_RESULT TEST_PENDING false
101 TEST_RESULT TEST_NEGATIVE false
102 TEST_RESULT TEST_POSITIVE false
------------------------------------------------------------------------
@Entity
@Table(name="constant_enum")
public class ConstantEnum implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="enum_code")
private Integer enumCode;
private boolean disabled;
@Column(name="enum_desc")
private String enumDesc;
@Column(name="enum_name")
private String enumName;
@Column(name="enum_type") // this is the discriminator
private String enumType;
//getters and setters
}
我最终删除了与数据库的连接,并在 class 本身中定义了静态变量,使用静态 ofValue
方法创建对象:
public class SomeClass implements Serializable {
public static final SomeClass MY_CONSTANT_1 = new SomeClass("static.value");
public static SomeClass [] values = new SomeClass []{
SomeClass .MY_CONSTANT_1,
...
};
private String name;
public SomeClass (String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static SomeClass ofValue(String name){
if(StringUtils.isEmpty(name)) return null;
for(SomeClass value : values) if(value .getName().equalsIgnoreCase(name)) return event;
throw new IllegalArgumentException(String.format("Couldn't convert value : %s into a valid %s object", name, SomeClass.class.getName()));
}
}
这样扩展如下:
public class ExtendedSomeClass extends SomeClass implements Serializable {
public static final SomeClass MY_CONSTANT_2 = new SomeClass ("static.value.2");
public static SomeClass[] values = new SomeClass[]{
SomeClass.MY_CONSTANT_2,
};
public static SomeClass ofValue(String name){
if(StringUtils.isEmpty(name)) return null;
for(SomeClass event : values) if(event.getName().equalsIgnoreCase(name)) return event;
return SomeClass.ofEvent(name);
}
}
而且我总是可以从 @RestController
端点连接 values
数组和 return 它来填充表单。