如果枚举不可扩展,则重构此代码的最佳方法

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.

EnumAEnumB 是两个不同的集合,它们代表逻辑上相同的标志的集合,但在每个标志中都有一些独占的值他们:

EnumB

public enum EnumB {
  READ_ONLY,
  READ_WRITE,
  LIKE_ENABLED
}

所以为了重构这个,我制作了一个抽象基础 class - EntityBase,并制作了 EntityAEntityB,此基础 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 的所有权限标志的列表。