Java Secret: Using an enum to build a State machine(Java秘术:用枚举构建一个状态机)

近期在读Hadoop#Yarn部分的源代码。读到状态机那一部分的时候,感到enmu的使用方法实在是太灵活了,在给并发编程网翻译一篇文章的时候,正好碰到一篇这种文章。就赶忙翻译下来,涨涨姿式。html

原文连接:http://www.javacodegeeks.com/2011/07/java-secret-using-enum-to-build-state.html
做者:Peter Lawrey    译者:陈振阳java

综述

Java中的enum比其它的语言中的都强大,这产生了很是多使人吃惊的使用方法。编程

本文中,我将列出Java中的enum的一些特性,而后将这些特性应用到一块儿构成一个状态机。并发

Enum的单例和工具类使用方法

你可以很easy地用一个enmu构建一个单例或者工具类。oracle

enum Singleton {
    INSTANCE;
}
enum Utility {
    ; // no instances
}

用enum实现一个接口

你也可以在一个enum中实现一个接口。app

interface Named {
    public String name();
    public int order();
}
enum Planets implements Named {
    Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune;
    // name() is implemented automagically.
    public int order() { return ordinal()+1; }
}

每一个enum实例,一个不一样的子类

你可以重载一个enum实例的方法。这将高效的给以个enum的实例一个本身的实现。jvm

// from http://download.oracle.com/javase/1,5.0/docs/guide/language/enums.html
public enum Operation {
  PLUS   { double eval(double x, double y) { return x + y; } },
  MINUS  { double eval(double x, double y) { return x - y; } },
  TIMES  { double eval(double x, double y) { return x * y; } },
  DIVIDE { double eval(double x, double y) { return x / y; } };

  // Do arithmetic op represented by this constant
  abstract double eval(double x, double y);
}

使用一个enum实现一个状态机

用上边的技术你可以作的是建立一个基于状态的enum。socket

在这个小样例中,一个解析器的状态机处理一个来自一个ByteBuffer的原始的XML。每一个状态都有本身的处理方法,假设没有足够的可用的数据,状态机可以返回来再次获取不少其它的数据。ide

状态之间的每一次变换都被定义,所有状态的代码在一个enum中。工具

interface Context {
    ByteBuffer buffer();
    State state();
    void state(State state);
}
interface State {
    /**
       * @return true to keep processing, false to read more data.
     */
    boolean process(Context context);
}
enum States implements State {
    XML {
        public boolean process(Context context) {
            if (context.buffer().remaining() < 16) return false;
            // read header
            if(headerComplete)
                context.state(States.ROOT);
            return true;
        }
    }, ROOT {
        public boolean process(Context context) {
            if (context.buffer().remaining() < 8) return false;
            // read root tag
            if(rootComplete)
                context.state(States.IN_ROOT);
            return true;
        }
    }
}

public void process(Context context) {
    socket.read(context.buffer());
    while(context.state().process(context));
}

使用这中方式,可以建立一个XML解析器,解析器可以处理10微秒内的数据包。大多数状况下。它跟你需要的同样高效。

Reference: Java Secret: Using an enum to build a State machine from our JCG partner Peter Lawrey at the Vanilla Java.

Related Articles:

相关文章
相关标签/搜索