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

    参考资料

  • 相关阅读:
    小tips: HTTP 请求过程示例图及名称解释
    小tips:使用vuecli2脚手架配置vant自定义主题
    axios使用备忘录
    知乎问题:为什么很多web项目还是使用 px,而不是 rem?
    小tips:HTML5的ruby标签实现给汉字加拼音、details标签实现折叠面板、原生进度条progress和度量meter
    ES6之常用开发知识点:入门(一)
    GitBook相关使用以及配置笔记
    小tips:使用vue-cli脚手架搭建项目,关于eslint语法检测配置
    小tips:JS/CSS实现字符串单词首字母大写
    vue动态子组件的实现方式
  • 原文地址:https://www.cnblogs.com/rollenholt/p/3962475.html
Copyright © 2011-2022 走看看