Java秘术:用枚举构建一个状态机

原文链接   作者:Peter Lawrey    译者:陈振阳

综述

Java中的enum比其他的语言中的都强大,这产生了很多令人惊讶的用法。本文中,我将列出Java中的enum的一些特性,然后将这些特性应用到一起构成一个状态机。

Enum的单例和工具类用法

你可以非常简单地用一个enum构建一个单例或者工具类。

</pre>
enum Singleton {
    INSTANCE;
}
enum Utility {
    ; // no instances
}

用enum实现一个接口

你也可以在一个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; }
}

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

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

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

在这个小例子中,解析器的状态机处理一个ByteBuffer里的原始的XML。每一个状态都有自己的处理方法,如果没有足够的可用的数据,状态机可以回来再次获取更多的数据。状态之间的每一次变换都被定义,所有状态的代码在一个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微秒内处理完数据包。大多数情况下,它跟你需要的一样高效。

时间: 2024-11-18 16:48:43

Java秘术:用枚举构建一个状态机的相关文章

Java理论与实践: 构建一个更好的HashMap

ConcurrentHashMap 是 Doug Lea的 util.concurrent 包的一部分,它提供 比Hashtable 或者 synchronizedMap 更高程度的并发性.而且,对于大多数成 功的 get() 操作它会设法避免完全锁定,其结果就是使得并发应用程序有着非 常好的吞吐量.这个月,BrianGoetz 仔细分析了 ConcurrentHashMap的代码, 并探讨 Doug Lea 是如何在不损失线程安全的情况下取得这么骄人成绩的. 在7月份的那期 Java理论与实践

云效公有云如何构建一个基于Composer的PHP项目

最近在将公司的持续集成架构做一个系统的调整,调整过程中受到了云效公有云团队大量的帮助,分享这篇内容希望能让更多的人了解和用好这个产品. 我会把我最近3个月的使用体会分成5个部分:使用云效公有云的动机.PHP项目集成.JS项目集成.JAVA项目集成.Docker类项目集成这5个分支来写. 因为近期公有云的迭代比较频繁,所以我的分享会比较的浅,点到为止,仅供参考,目录: 1.云效公有云如何耦合进我们的业务 2.如何构建一个基于Composer的PHP项目 3.如何构建一个基于NodeJS的前后端项目

云效(原RDC)如何构建一个基于Composer的PHP项目

最近在将公司的持续集成架构做一个系统的调整,调整过程中受到了RDC团队大量的帮助,所以利用国庆时间写了几篇RDC的分享,希望能让更多的人了解和用好RDC这个产品. 我会把我最近3个月的使用体会分成5个部分:使用RDC的动机.PHP项目集成.JS项目集成.JAVA项目集成.Docker类项目集成这5个分支来写 因为近期RDC的迭代比较频繁,所以我的分享会比较的浅,点到为止,仅供参考,目录: 1.RDC如何耦合进我们的业务 2.如何构建一个基于Composer的PHP项目 3.如何构建一个基于Nod

云效(原RDC)如何构建一个基于NodeJS的前后端项目

最近在将公司的持续集成架构做一个系统的调整,调整过程中受到了RDC团队大量的帮助,所以利用国庆时间写了几篇RDC的分享,希望能让更多的人了解和用好RDC这个产品. 我会把我最近3个月的使用体会分成5个部分:使用RDC的动机.PHP项目集成.JS项目集成.JAVA项目集成.Docker类项目集成这5个分支来写 因为近期RDC的迭代比较频繁,所以我的分享会比较的浅,点到为止,仅供参考,目录: 1.RDC如何耦合进我们的业务 2.如何构建一个基于Composer的PHP项目 3.如何构建一个基于Nod

java中的枚举类型详细介绍_java

枚举中有values方法用于按照枚举定义的顺序生成一个数组,可以用来历遍.我们自定义的枚举类都是继承自java.lang.Enum,拥有一下实例中的功能: 复制代码 代码如下: //: enumerated/EnumClass.java // Capabilities of the Enum class import static net.mindview.util.Print.*; enum Shrubbery { GROUND, CRAWLING, HANGING } public clas

Python中的线性优化,第 2 部分 在云中构建一个可扩展的基础架构

简介 这个由三部分组成的系列文章的第 1 部分介绍了在 Python 中使用 Pyomo 库进行线性优化的 基础知识.现在我们将介绍如何扩展它.Python 缺乏真实的操作系统线程,该如何扩展它?本文将向您介绍 如何组合使用这些技术来创建一个实际的可扩展基础架构,该架构可用于构建一个 Pyomo Web 解决方案.我 们组合使用了一个单线程事件循环.一个 AMQP 服务器和工作线程流程来创建一个模式,利用该模式扩展一个 线性优化系统.该基础架构也适用于 Python 或 Ruby 中的许多通用计

Java中的基础构建模块(第五章)

Java中的基础构建模块 Java平台类库包含了丰富的并发基础构建模块,例如线程安全的容器类以及各种用于协调多个相互协作的线程控制流的同步工具类. 1.同步容器类 同步容器类都是线程安全的,但在某些情况下可能需要额外的客户端加锁来保护复合操作.常见的复合操作包括:迭代.跳转(在容器内元素之间).条件运算(例如"若没有则添加"). 隐式迭代:某些情况下迭代操作会隐藏起来.如下代码中println调用Set的toString方法,然后对Set中的对象进行迭代调用toString方法: pu

《ANTLR 4权威指南》——3.4 构建一个语言类应用程序

3.4 构建一个语言类应用程序 我们继续完成能够处理数组初始化语句的示例程序,下一个目标是能够翻译初始化语句,而不仅仅是能够识别它们.例如,我们想要将Java中,类似{ 99, 3, 451 }的short数组翻译成"\u0063\u0003\u01c3".注意,其中十进制数字99的十六进制表示是63. 为了完成这项工作,程序必须能够从语法分析树中提取数据.最简单的方案是使用ANTLR内置的语法分析树遍历器进行深度优先遍历,然后在它触发的一系列回调函数中进行适当的操作.正如我们之前看到

全面解读Java中的枚举类型enum的使用_java

关于枚举大多数地方写的枚举都是给一个枚举然后例子就开始switch,可是我想说,我代码里头来源的数据不太可能就是枚举,通常是字符串或数字,比如一个SQL我解析后首先判定SQL类型,通过截取SQL的token,截取出来可能是SELECT.DELETE.UPDATE.INSERT.ALTER等等,但是都是字符串,此时我想用枚举就不行了,我要将字符串转换成枚举怎么转呢,类似的情况还有从数据库取出数据根据一些类型做判定,从页面传入数据,根据不同的类型做不同的操作,但是都是字符串,不是枚举,悲剧的是我很少