使用enum創建簡單的狀態機

Overview

The enum in Java is more powerful than many other languages which can lead to surprising uses.html

In this article, I outline some the individual features of enum in Java, and put them together to form a state machine.java

Enum for Singleton and Utility class

You can use an enum as a Singleton or Utility very simply.編程

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

Enum to implement an interface

You can also implement an interface in an enum.oracle

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; }
}

Each Enum Instance a different sub-class

You can override the behaviour of an instance. This effectively give the instance a different sub-class of the enum with its own implementation.socket

// 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);
}

Using an enum as a state machine
What you can do with all these techniques is to create a enum based statement.
ide

In this short example, a parser state machine processes raw XML from a ByteBuffer. Each state has its own process method and if there is not enough data available, the state machine can return to retrieve more data. Each transition between states is well defined and the code for all states is together in one enum.ui

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));
}

寫在後面

我的感受使用若是想真的實現一個完整的finite-state machine的話,上面的例子真的是太基礎了。不過參考上面的用法能夠幫助咱們減小不少的if else if等代碼。另外涉及到「分支處理」的狀況,在實際的工做中,我更多的仍是會選擇「策略模式」。this

參考資料

此貼從覺得大神的博客中截取,轉帖地址已放上,感興趣的能夠到裏面看看spa

相關文章
相關標籤/搜索