有限状态机( Finite State Machine )JAVA 版

介绍

有限状态机通常用于模拟序列逻辑,换句话说,就是用于代表和控制执行流程。

有限状态机所需条件:

  • 一个物体只有固定的几种状态(例如交通灯只有绿灯、黄灯和红灯三个状态)。
  • 有固定的变化顺序(例如交通灯只能绿灯->黄灯->红灯->绿灯循环)
  • 物体同一时间点上只有一种状态。

例子

这里拿一个空调做例子,图是用了别人的,这里说明下下面三个状态的意思:

Off:空调关机

FanOnly:空调仅吹风

Cool:空调制冷

有限状态机( Finite State Machine )JAVA 版

原始的解决办法

StateEnum

用枚举类定义三种状态

package org.example.origin;

public enum StateEnum {
    POWER_OFF, FAN_ONLY, COOL
}

OriginAction

pressPowerOff() 表示点开关按钮,pressCool() 表示点击制冷按钮。

package org.example.origin;

public class OriginAction {
    private StateEnum stateEnum;

    public OriginAction() {
        this.stateEnum = StateEnum.POWER_OFF;
    }

    public void pressPowerOff() {
        // 关机->吹风
        if (stateEnum == StateEnum.POWER_OFF) {
            this.stateEnum = StateEnum.FAN_ONLY;
            System.out.println("Power on succeed.");
        } else {
            // 吹风或制冷->关机
            this.stateEnum = StateEnum.POWER_OFF;
            System.out.println("Power off succeed.");
        }
    }

    public void pressCool() {
        if (stateEnum == StateEnum.POWER_OFF) {
            System.out.println("Cool failed because power off.");
        } else if (stateEnum == StateEnum.FAN_ONLY) {
            // 吹风->制冷
            this.stateEnum = StateEnum.COOL;
            System.out.println("Open cool succeed.");
        } else {
            // 制冷->吹风
            this.stateEnum = StateEnum.FAN_ONLY;
            System.out.println("Close cool succeed");
        }
    }
}

OriginTest

编写测试类

package org.example.origin;

public class OriginTest {
    public static void main(String[] args) {
        OriginAction originAction = new OriginAction();
        originAction.pressCool();
        originAction.pressPowerOff();
        originAction.pressCool();
        originAction.pressCool();
        originAction.pressPowerOff();
    }
}

执行结果:

Cool failed because power off.
Power on succeed.
Open cool succeed.
Close cool succeed
Power off succeed.

使用有限状态机解决

FiniteStateMachineEnum

这里使用了 Java 的枚举类,确保了类型约束。

package org.example.state;

public enum FiniteStateMachineEnum {

    POWER_OFF {
        // 关机->吹风
        @Override
        public FiniteStateMachineEnum pressPowerOff() {
            System.out.println("Power on succeed.");
            return FiniteStateMachineEnum.FAN_ONLY;
        }

        // 无效
        @Override
        public FiniteStateMachineEnum pressCool() {
            System.out.println("Cool failed because power off.");
            return FiniteStateMachineEnum.POWER_OFF;
        }
    },

    FAN_ONLY {
        // 吹风->关机
        @Override
        public FiniteStateMachineEnum pressPowerOff() {
            System.out.println("Power off succeed.");
            return FiniteStateMachineEnum.POWER_OFF;
        }

        // 吹风->制冷
        @Override
        public FiniteStateMachineEnum pressCool() {
            System.out.println("Open cool succeed.");
            return FiniteStateMachineEnum.COOL;
        }
    },

    COOL {
        // 制冷->关机
        @Override
        public FiniteStateMachineEnum pressPowerOff() {
            System.out.println("Power off succeed.");
            return FiniteStateMachineEnum.POWER_OFF;
        }

        // 制冷->吹风
        @Override
        public FiniteStateMachineEnum pressCool() {
            System.out.println("Close cool succeed");
            return FiniteStateMachineEnum.FAN_ONLY;
        }
    };

    public abstract FiniteStateMachineEnum pressPowerOff();

    public abstract FiniteStateMachineEnum pressCool();
}

FiniteStateMachineTest

编写测试类

package org.example.state;

public class FiniteStateMachineTest {
    public static void main(String[] args) {
        FiniteStateMachineEnum stateEnum = FiniteStateMachineEnum.POWER_OFF;
        stateEnum.pressCool()
                .pressPowerOff()
                .pressCool()
                .pressCool()
                .pressPowerOff();
    }
}

执行结果:

Cool failed because power off.
Power on succeed.
Open cool succeed.
Close cool succeed
Power off succeed.

总结

两种方法的运行结果是一样的,但是有限状态机的写法更加简洁明了。传统方法在简单的条件下还可以应付,但是如果面对复杂的执行逻辑顺序,只有通过有限状态机来解决了,而且代码更加简洁明了,易于维护。

原创文章,作者:Smith,如若转载,请注明出处:https://www.inlighting.org/archives/finite-state-machine-in-java

打赏 微信扫一扫 微信扫一扫
SmithSmith
上一篇 2019年8月3日 上午12:18
下一篇 2021年1月1日 下午1:33

相关推荐

  • 用 Java 实现一个可用的布隆过滤器(Bloom Filter)

    布隆过滤器可以使用极少的空间来判断一个元素是否存在某一个集合中,本文不具体讨论布隆过滤器的原理,而是探讨如何实现一个可用的布隆过滤器。 本文代码提取自 Apache ORC 项目。…

    2021年3月7日
    1.8K0
  • Spring Boot 2 + Spring Security 5 + JWT 的单页应用

    此前我已经写过一篇类似的教程,但那时候使用了投机的方法,没有尊重 Spring Security 的官方设计,自己并不感到满意。这段时间比较空,故重新研究了一遍。 老版本:http…

    2019年8月3日
    1.8K0
  • JDK 动态代理踩坑

    最近阅读 Hadoop 的源码,看到各种动态代理,打算学习下。虽然以前也学过,但是感觉就是死记硬背的代码,有些地方根本不懂。温习了一遍网上 JDK 动态代理的教程后,自己尝试再一次…

    2021年1月1日
    1.1K0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注