我刚刚发现Java允许枚举实现接口。它的一个好的用例是什么?


当前回答

最常见的用法是将两个枚举的值合并到一个组中,并以类似的方式对待它们。例如,查看如何加入水果和蔬菜。

其他回答

枚举就像Java类,它们可以有构造函数、方法等。唯一不能使用它们的是new EnumName()。实例是在枚举声明中预定义的。

上面提到的策略并没有充分强调使用枚举的策略模式的轻量级实现:

public enum Strategy {

  A {
    @Override
    void execute() {
      System.out.print("Executing strategy A");
    }
  },
  
  B {
    @Override
    void execute() {
      System.out.print("Executing strategy B");
    }
  };

  abstract void execute();
}

你可以把所有的策略放在一个地方,而不需要为每个策略单独编译单元。你得到了一个很好的动态调度:

Strategy.valueOf("A").execute();

使java读起来几乎像一种美味的松散类型语言!

我在一个接口中使用了一个内部枚举来描述一个策略来保持实例控制(每个策略都是一个Singleton)。

public interface VectorizeStrategy {

    /**
     * Keep instance control from here.
     * 
     * Concrete classes constructors should be package private.
     */
    enum ConcreteStrategy implements VectorizeStrategy {
        DEFAULT (new VectorizeImpl());

        private final VectorizeStrategy INSTANCE;

        ConcreteStrategy(VectorizeStrategy concreteStrategy) {
            INSTANCE = concreteStrategy;
        }

        @Override
        public VectorImageGridIntersections processImage(MarvinImage img) {
            return INSTANCE.processImage(img);
        }
    }

    /**
     * Should perform edge Detection in order to have lines, that can be vectorized.
     * 
     * @param img An Image suitable for edge detection.
     * 
     * @return the VectorImageGridIntersections representing img's vectors 
     * intersections with the grids.
     */
    VectorImageGridIntersections processImage(MarvinImage img);
}

枚举实现该策略的事实便于允许枚举类充当其所包含的Instance的代理。其中也实现了接口。

它是一种strategyEnumProxy:P,客户端代码看起来像这样:

VectorizeStrategy.ConcreteStrategy.DEFAULT.processImage(img);

如果它没有实现接口,它将是:

VectorizeStrategy.ConcreteStrategy.DEFAULT.getInstance().processImage(img);

在jar文件中创建常量时,让用户扩展枚举值通常是有帮助的。我们为PropertyFile键使用了枚举,但是因为没有人能够添加任何新的键而陷入了僵局!下面的效果会好得多。

考虑到:

public interface Color {
  String fetchName();
}

and:

public class MarkTest {

  public static void main(String[] args) {
    MarkTest.showColor(Colors.BLUE);
    MarkTest.showColor(MyColors.BROWN);
  }

  private static void showColor(Color c) {
    System.out.println(c.fetchName());
  }
}

一个容器中可以有一个enum:

public enum Colors implements Color {
  BLUE, RED, GREEN;
  @Override
  public String fetchName() {
    return this.name();
  }
}

用户可以扩展它来添加自己的颜色:

public enum MyColors implements Color {
  BROWN, GREEN, YELLOW;
  @Override
  public String fetchName() {
    return this.name();
  }
}

枚举不只是表示被动的集合(例如颜色)。它们可以表示具有功能的更复杂的对象,因此你可能想要在这些对象上添加更多的功能——例如,你可能有诸如Printable、Reportable等接口,以及支持这些接口的组件。