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

总结

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

Java

Spring Boot 2 + Spring Security 5 + JWT 的单页应用

2019-8-3 0:18:00

Java

JDK 动态代理踩坑

2021-1-1 13:33:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
搜索