如果枚举不可扩展,则重构此代码的最佳方法
Best way to refactor this code, if enums are not extensible
考虑以下 class 表示实体并具有 return 数据类型 EnumA
的方法
实体A class:
public class EntityA
{
public Set<EnumA> getProcessedFlags() { ... }
}
枚举A:
public enum EnumA {
READ_ONLY,
READ_WRITE,
PERMISSION_DENIED,
COMMENT_ENABLED
}
现在我得到了再添加一个EntityB的需求,这与EntityA相似,但逻辑上不同。 (相同的方法签名但不同的实现:
还有一件事,return 值在 EntityA 中是 EnumA,对于 实体B.
EnumA 和 EnumB 是两个不同的集合,它们代表逻辑上相同的标志的集合,但在每个标志中都有一些独占的值他们:
EnumB
public enum EnumB {
READ_ONLY,
READ_WRITE,
LIKE_ENABLED
}
所以为了重构这个,我制作了一个抽象基础 class - EntityBase,并制作了 EntityA 和 EntityB,此基础 class.
的子项
问题是枚举不可扩展,有重构这个的好方法吗?
我想创建如下所示的 class 结构:
public enum EnumBase {}
public enum EnumA extends EnumBase {}
public enum EnumB extends EnumBase {}
public abstract class EntityBase
{
public Set<? extends EnumBase> getProcessedFlags();
}
public class EntityA extends EntityBase
{
public Set<EnumA> getProcessedFlags() { ... }
}
public class EntityB extends EntityBase
{
public Set<EnumB> getProcessedFlags() { ... }
}
既然java中的枚举是不可扩展的,我们能不能有一些更好的设计来维护这个EntityBaseclass?
很难在没有更多上下文的情况下提供具体建议,但值得注意的是枚举可以共享接口,因此您可以尝试这样的事情:
interface Base {
String name();
}
interface A extends Base {}
interface B extends Base {}
public enum EnumBase implements A, B {
READ_ONLY,
READ_WRITE
}
public enum EnumA implements A {
PERMISSION_DENIED,
COMMENT_ENABLED
}
public enum EnumB implements B {
LIKE_ENABLED
}
public abstract class EntityBase<F extends Base> {
public abstract Set<F> getProcessedFlags();
}
public class EntityA extends EntityBase<A> {
@Override
public Set<A> getProcessedFlags() { ... }
}
public class EntityB extends EntityBase<B> {
@Override
public Set<B> getProcessedFlags() { ... }
}
一种不同的解决方案是对所有 PermissionsFlags 使用一个枚举,然后添加一个属性,允许您检查 PermissionFlag 是否可以与此一起使用 class。
public enum PermissionFlag {
READ_ONLY,
READ_WRITE,
PERMISSION_DENIED(EntityA.class),
COMMENT_ENABLED(EntityA.class),
LIKE_ENABLED(EntityB.class);
private final Class<?> useForClass;
PermissionFlag() {
this(null);
}
PermissionFlag(Class<?> useForClass) {
this.useForClass = useForClass;
}
/**
* Check if given class can be used for this PermissionFlag.
*/
public boolean useForClass(Class<?> clazz) {
return useForClass == null || useForClass.equals(clazz);
}
/**
* Returns a Stream consisting of all the PermissionFlags that can be used with the given class.
*/
public static Stream<PermissionFlag> getPermissionsFlags(Class<?> clazz){
return Stream.of(values()).filter(flag -> flag.useForClass(clazz));
}
}
然后您可以使用 getPermissionFlags(EntityA.class).collect(Collectors.toList())
获取 EntityA
的所有权限标志的列表。
考虑以下 class 表示实体并具有 return 数据类型 EnumA
的方法实体A class:
public class EntityA
{
public Set<EnumA> getProcessedFlags() { ... }
}
枚举A:
public enum EnumA {
READ_ONLY,
READ_WRITE,
PERMISSION_DENIED,
COMMENT_ENABLED
}
现在我得到了再添加一个EntityB的需求,这与EntityA相似,但逻辑上不同。 (相同的方法签名但不同的实现:
还有一件事,return 值在 EntityA 中是 EnumA,对于 实体B.
EnumA 和 EnumB 是两个不同的集合,它们代表逻辑上相同的标志的集合,但在每个标志中都有一些独占的值他们:
EnumB
public enum EnumB {
READ_ONLY,
READ_WRITE,
LIKE_ENABLED
}
所以为了重构这个,我制作了一个抽象基础 class - EntityBase,并制作了 EntityA 和 EntityB,此基础 class.
的子项问题是枚举不可扩展,有重构这个的好方法吗?
我想创建如下所示的 class 结构:
public enum EnumBase {}
public enum EnumA extends EnumBase {}
public enum EnumB extends EnumBase {}
public abstract class EntityBase
{
public Set<? extends EnumBase> getProcessedFlags();
}
public class EntityA extends EntityBase
{
public Set<EnumA> getProcessedFlags() { ... }
}
public class EntityB extends EntityBase
{
public Set<EnumB> getProcessedFlags() { ... }
}
既然java中的枚举是不可扩展的,我们能不能有一些更好的设计来维护这个EntityBaseclass?
很难在没有更多上下文的情况下提供具体建议,但值得注意的是枚举可以共享接口,因此您可以尝试这样的事情:
interface Base {
String name();
}
interface A extends Base {}
interface B extends Base {}
public enum EnumBase implements A, B {
READ_ONLY,
READ_WRITE
}
public enum EnumA implements A {
PERMISSION_DENIED,
COMMENT_ENABLED
}
public enum EnumB implements B {
LIKE_ENABLED
}
public abstract class EntityBase<F extends Base> {
public abstract Set<F> getProcessedFlags();
}
public class EntityA extends EntityBase<A> {
@Override
public Set<A> getProcessedFlags() { ... }
}
public class EntityB extends EntityBase<B> {
@Override
public Set<B> getProcessedFlags() { ... }
}
一种不同的解决方案是对所有 PermissionsFlags 使用一个枚举,然后添加一个属性,允许您检查 PermissionFlag 是否可以与此一起使用 class。
public enum PermissionFlag {
READ_ONLY,
READ_WRITE,
PERMISSION_DENIED(EntityA.class),
COMMENT_ENABLED(EntityA.class),
LIKE_ENABLED(EntityB.class);
private final Class<?> useForClass;
PermissionFlag() {
this(null);
}
PermissionFlag(Class<?> useForClass) {
this.useForClass = useForClass;
}
/**
* Check if given class can be used for this PermissionFlag.
*/
public boolean useForClass(Class<?> clazz) {
return useForClass == null || useForClass.equals(clazz);
}
/**
* Returns a Stream consisting of all the PermissionFlags that can be used with the given class.
*/
public static Stream<PermissionFlag> getPermissionsFlags(Class<?> clazz){
return Stream.of(values()).filter(flag -> flag.useForClass(clazz));
}
}
然后您可以使用 getPermissionFlags(EntityA.class).collect(Collectors.toList())
获取 EntityA
的所有权限标志的列表。