使用enum建立简单的状态机

简介:

Overview

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

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

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.

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.

// 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.

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.

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等代码。另外涉及到“分支处理”的情况,在实际的工作中,我更多的还是会选择“策略模式”。

参考资料

目录
相关文章
|
9月前
|
C++
成员初始化表的执行顺序与顺写顺序无关
成员初始化表的执行顺序与顺写顺序无关
66 0
|
1月前
|
JSON C# 数据格式
【Azure Function】C#独立工作模式下参数类型 ServiceBusReceivedMessage 无法正常工作
Cannot convert input parameter 'message' to type 'Azure.Messaging.ServiceBus.ServiceBusReceivedMessage' from type 'System.String'.
115 73
|
9月前
|
存储 数据处理 C语言
自己建立结构体类型
自己建立结构体类型
61 0
|
9月前
|
网络协议 Linux
Linux网络编程(TCP状态转换关系)
Linux网络编程(TCP状态转换关系)
78 0
|
传感器 算法 安全
状态机设计举例
⭐本专栏针对FPGA进行入门学习,从数电中常见的逻辑代数讲起,结合Verilog HDL语言学习与仿真,主要对组合逻辑电路与时序逻辑电路进行分析与设计,对状态机FSM进行剖析与建模。
200 0
状态机设计举例
【AutoSAR实战订阅系列】Handle-ID分配和 PDU之间的链接关系
【AutoSAR实战订阅系列】Handle-ID分配和 PDU之间的链接关系
【AutoSAR实战订阅系列】Handle-ID分配和 PDU之间的链接关系
|
SQL Java 数据库连接
Hibernate的三种状态及相互转化
Hibernate的三种状态及相互转化
271 0
Hibernate的三种状态及相互转化
|
缓存 前端开发
【译】React v16.4.0:你可能并不需要派生状态(Derived State)
很长一段时间,componentWillReceiveProps生命周期是在不进行额外render的前提下,响应props中的改变并更新state的唯一方式。在16.3版本中,我们介绍了一个新的替代生命周期getDerivedStateFromProps去更安全地解决相同的问题。
2580 0
重构——25将双向关联改为单向关联(Change Bidirectional Association to Unidirectional)
将双向关联改为单向关联(Change Bidirectional Association to Unidirectional):两个类之间有双向关联,但其中一个类如今不再需要另一个类的特性;去掉不必要的关联
1812 0