Java枚举 - 字段,抽象方法和类级别图之间的选择



我已经写了一个java枚举,其中值具有各种属性。这些属性可以通过以下任何方式存储:

使用字段:

enum Eenum {
  V1(p1),
  V2(p2);
  private final A attr;
  public A attr() { return attr; }
  private Eenum(A attr) {
    this.attr = attr;
  }
}

使用抽象方法:

enum Eenum {
  V1 {
    public A attr() { return p1; }
  },
  V2 {
    public A attr() { return p2; }
  }
  public abstract A attr();
}

使用类级别地图:

enum Eenum {
  V1,
  V2;
  public A attr() { return attrs.get(this); }
  private static final Map<Eenum, A> attrs;
  static {
    ImmutableMap.Builder<Eenum, A> builder = ImmutableMap.builder();
    builder.put(V1, p1);
    builder.put(V2, p2);
    attrs = builder.build();
  }
}

我应该如何决定何时更喜欢哪个?

谢谢!

我会做您认为最简单的那个。

通常,我不编写可以使用数据实现的代码。我会使用第一个。

我的实际用例具有一些与所有枚举值无关的属性

如果根据属性有意义,则可以使用这些方法的组合。

第四个选项是没有抽象方法。

enum Eenum {
  V1 {
    public A attr() { return p1; }
  },
  V2 {
    public A attr() { return p2; }
  }, 
  V3, V4, V5, V6;
  public A attr() { return defaultA; }
}

都不是。这样做:

interface HasAttr<T> {
    T attr();
}
enum Eenum implements HasAttr<A> {
    // use "fields" version - ideally with constructor version
    public A attr() {
        return field;
    }
}

此模式遵循基本的抽象类型设计模式,该模式允许使用:

public void someMethod(HasAttr<A> hasAttr);  // pass anything that is HasAttr<a>

优先于固定类型:

public void someMethod(Eenum eenum); // locked into passing an Eenum

,而且重要的是,要模拟测试更容易,尤其是如果您的枚举使用真实连接等。

我授予您,所有这些仅在枚举是"不平凡"的情况下才适用。如果这只是一个普通的旧枚举,我同意这只是代码膨胀(我也很讨厌)

(我正在回答自己的问题,以便在尝试事物时分享一些我学到的东西。)

这是您应要求的问题,以决定您的具体情况:

1:属性值是否涉及前向引用?

有时V1的属性可能需要引用V2,反之亦然。这不是罕见的情况。如果您要处理这样的enum,方法1根本不起作用。编译器将(正确)抱怨非法远期参考。其他两种方法都可以使用。

现在,如果属性值计算昂贵且常数,则您只想计算一次。使用方法2,您必须每个枚举值引入本地变量,并在那里缓存结果。这是冗长的,但会给您更好的表现。使用方法3,无论如何结果仅计算一次,因此不必做任何额外的工作。这是更可读的,但性能比方法2。根据您的案件中的特定交易,它们之间的设计。

2:我需要缓存结果吗?

请参阅上一个子弹的第二段。

如果没有正向引用,则可以使用方法1。但是,如果属性计算中涉及的计算很复杂,那么您最好使用另一种方法之一。

3:属性是否与所有枚举值相关?

如果没有,那么从逻辑上讲,您应该在此处使用Map。也就是说,方法3。

4:某些枚举值的某些属性是否有任何默认值?

如果是这样,您可以使用所有三种方法,并且它们都提供不同的权衡。

使用方法1:您将定义一个辅助构造函数,该辅助构造函数将属性初始化为默认值。如果有多个此类属性,这可能不是可行的方法。

使用方法2:这实际上就像彼得·劳瑞(Peter Lawrey)上面建议的"第四"方法。您将有一个方法返回enum的主体中的默认值。一些枚举值将覆盖此方法以返回其他值。这再次是冗长的。

使用方法3:效率较低。以其他方式好。

最新更新