有限状态机( 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

相关推荐

  • Spring Boot2 + Spring Security + Thymeleaf 简单教程

    因为有一个项目需采用MVC构架,所以学习了Spring Security并记录下来,希望大家一起学习提供意见 如果有疑问,请在 GitHub 中发布 issue,我有空会为大家解答…

    2019年8月2日
    1.5K0
  • JDK 动态代理踩坑

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

    2021年1月1日
    1.1K0
  • Shiro + JWT + Spring Boot Restful 简易教程

    GitHub 地址:https://github.com/Smith-Cruise/Spring-Boot-Shiro 序言 我也是半路出家的人,如果大家有什么好的意见或批评,请务…

    2019年8月1日
    1.6K0

发表回复

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