考虑以下类,它们表示一个实体,并具有返回类型为EnumA的数据的方法
实体A类:
public class EntityA
{
public Set<EnumA> getProcessedFlags() { ... }
}
EnumA:
public enum EnumA {
READ_ONLY,
READ_WRITE,
PERMISSION_DENIED,
COMMENT_ENABLED
}
现在,我需要再添加一个EntityB,它与EntityA相似,但在逻辑上不同。(相同的方法签名但不同的实现:
还有一件事,返回值是EntityA中的EnumAntityB的**EnumB。
EnumA和EnumB是两个不同的集合,它们表示逻辑上相同的标志的集合,但每个标志中都有一些互斥值:
EnumB
public enum EnumB {
READ_ONLY,
READ_WRITE,
LIKE_ENABLED
}
因此,为了重构它,我创建了一个抽象基类-EntityBase,并将EntityA和EntityB都作为该基类的子级。
问题是枚举不可扩展,有没有一个好的方法来重构它?
我想创建如下的类结构:
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中的枚举是不可扩展的,我们能有一些更好的设计来维护这个EntityBase类吗?
如果没有更多的上下文,很难提供具体的建议,但值得注意的是,枚举可以共享接口,所以你可以尝试这样的方法:
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是否可以与此类一起使用。
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
的所有权限标志的列表。