Java中的有限状态机(设计模式——状态模式)

 更新时间:2023年08月21日 10:28:31   作者:bjxiaxueliang  
这篇文章主要介绍了Java中的有限状态机(设计模式——状态模式),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Java有限状态机 (设计模式——状态模式)

编写代码的时候,有时会遇见较为复杂的 swith...case... if...else... 语句。

这一刻有时会想到状态机,用 有限状态机 替换 swith...case... if...else... 可以:

  • 降低程序的复杂度;
  • 提高程序的可维护性;
  • 状态机模式体现了开闭原则和单一职责原则。
    每个状态都是一个子类,增加状态就要增加子类;修改状态只要修改一个类就行了。

以上是有限状态机的好处。

其亦有 缺点

  • 使用状态机子类会增多,也就是类膨胀,这点需要程序员在开发中自己衡量。

状态模式定义

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.

允许对象在其内部状态发生变化时更改其行为。

看起来像更改了其类 (这翻译不好,这里 应该是体现了其封装性:外部的调用不用知道其内部如何实现状态和行为变化的)。

举个例子

我们每天都乘坐电梯,电梯有四种状态: 开门、关门、运行、停止。

Col1开门 行为关门 行为运行 行为停止 行为
开门 态noyesnono
关门 态yesnoyesyes
运行 态nononoyes
停止 态yesnoyesno

LiftState.java

/**
 * 定义电梯行为:打开、关闭、运行、停止
 */
public abstract class LiftState {
    // 拥有一个电梯对象,用于更新电梯当前状态
    protected Lift mLift;
    /**
     * 通过构造函数引入电梯的实例化对象
     *
     * @param lift
     */
    public LiftState(Lift lift) {
        this.mLift = lift;
    }
    /**
     * 行为:打开电梯门
     */
    public abstract void open();
    /**
     * 行为:关闭电梯门
     */
    public abstract void close();
    /**
     * 行为:电梯运行
     */
    public abstract void run();
    /**
     * 行为:电梯停止运行
     */
    public abstract void stop();
}

电梯的四种状态

public class OpeningState extends LiftState {
    public OpeningState(Lift lift) {
        super(lift);
    }
    @Override
    public void open() {
        // 执行开门动作
        System.out.println("执行开门动作");
    }
    @Override
    public void close() {
        // 执行关门动作
        // 1、转化为关门状态
        mLift.setState(mLift.getCloseingState());
        // 2、关门
        mLift.close();
    }
    @Override
    public void run() {
        // do noting
        // 开门状态,不能执行运行动作
    }
    @Override
    public void stop() {
        // do noting
        // 开门状态下,不执行停止动作
    }
}
public class ClosingState extends LiftState {
    public ClosingState(Lift lift) {
        super(lift);
    }
    @Override
    public void open() {
        // 执行开门动作
        // 1、变化为开门状态
        this.mLift.setState(mLift.getOpenningState());
        // 2、开门
        this.mLift.open();
    }
    @Override
    public void close() {
        System.out.println("执行关门动作");
    }
    @Override
    public void run() {
        // 运行动作
        // 1、运行状态
        this.mLift.setState(mLift.getRunningState());
        // 2、运行动作
        this.mLift.run();
    }
    @Override
    public void stop() {
        // 停止动作
        // 1、转化为停止状态
        this.mLift.setState(mLift.getStoppingState());
        // 2、停止
        this.mLift.stop();
    }
}
public class RunningState extends LiftState {
    public RunningState(Lift lift) {
        super(lift);
    }
    @Override
    public void open() {
        // do noting
    }
    @Override
    public void close() {
        // do noting
    }
    @Override
    public void run() {
        // 运行动作
        System.out.println("电梯上下运行中...");
    }
    @Override
    public void stop() {
        // 停止动作
        // 1、转化为停止状态
        this.mLift.setState(mLift.getStoppingState());
        // 2、停止动作
        this.mLift.stop();
    }
}
public class StoppingState extends LiftState {
    public StoppingState(Lift lift) {
        super(lift);
    }
    @Override
    public void open() {
        // 开门动作
        // 1、开门状态
        this.mLift.setState(mLift.getOpenningState());
        // 2、执行开门动作
        this.mLift.open();
    }
    @Override
    public void close() {
        // do noting
    }
    @Override
    public void run() {
        // 运行动作
        // 1、运行状态
        this.mLift.setState(mLift.getRunningState());
        // 2、运行动作
        this.mLift.run();
    }
    @Override
    public void stop() {
        // 电梯停止动作
        System.out.println("电梯停止运行...");
    }
}

定义电梯类

/**
 * 定义电梯类
 */
public class Lift {
    //定义出电梯的所有状态
    private LiftState openningState;
    private LiftState closingState;
    private LiftState runningState;
    private LiftState stoppingState;
    // 定义当前电梯状态
    private LiftState mCurState;
    /**
     * 构造方法
     */
    public Lift() {
        openningState = new OpeningState(this);
        closingState = new ClosingState(this);
        runningState = new RunningState(this);
        stoppingState = new StoppingState(this);
    }
    /**
     * 执行开门动作
     */
    public void open() {
        mCurState.open();
    }
    /**
     * 执行关门动作
     */
    public void close() {
        mCurState.close();
    }
    /**
     * 执行运行动作
     */
    public void run() {
        mCurState.run();
    }
    /**
     * 执行停止动作
     */
    public void stop() {
        mCurState.stop();
    }
    // ##################设置当前电梯状态#####################
    /**
     * 设置当前电梯状态
     *
     * @param state
     */
    public void setState(LiftState state) {
        this.mCurState = state;
    }
    // ###################获取电梯的全部状态####################
    public LiftState getOpenningState() {
        return openningState;
    }
    public LiftState getCloseingState() {
        return closingState;
    }
    public LiftState getRunningState() {
        return runningState;
    }
    public LiftState getStoppingState() {
        return stoppingState;
    }
}

运行

public static void main(String[] args) {
        Lift lift = new Lift();
        lift.setState(new ClosingState(lift));
        lift.open();
        lift.close();
        lift.run();
        lift.stop();
    }

运行结果

执行开门动作
执行关门动作
电梯上下运行中...
电梯停止运行...

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java如何根据不同系统动态获取换行符和盘分割符

    Java如何根据不同系统动态获取换行符和盘分割符

    这篇文章主要介绍了Java如何根据不同系统动态获取换行符和盘分割符,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 简单解析execute和submit有什么区别

    简单解析execute和submit有什么区别

    这篇文章主要介绍了简单解析execute和submit有什么区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • java中实现控制台打印sql语句方式

    java中实现控制台打印sql语句方式

    这篇文章主要介绍了java中实现控制台打印sql语句方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Java手动实现Redis的LRU缓存机制

    Java手动实现Redis的LRU缓存机制

    在Java中LRU的实现方式是使用HashMap结合双向链表,HashMap的值是双向链表的节点,双向链表的节点也保存一份key value。
    2021-05-05
  • 详解JavaFX桌面应用开发-Group(容器组)

    详解JavaFX桌面应用开发-Group(容器组)

    这篇文章主要介绍了JavaFX桌面应用开发-Group(容器组),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • java使用RSA加密方式实现数据加密解密的代码

    java使用RSA加密方式实现数据加密解密的代码

    这篇文章给大家分享java使用RSA加密方式实现数据加密解密,通过实例代码文字相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下
    2019-11-11
  • 使用Spring中的scope配置和@scope注解

    使用Spring中的scope配置和@scope注解

    这篇文章主要介绍了使用Spring中的scope配置和@scope注解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • 使用Java实现DNS域名解析的简单示例

    使用Java实现DNS域名解析的简单示例

    这篇文章主要介绍了使用Java实现DNS域名解析的简单示例,包括对一个动态IP主机的域名解析例子,需要的朋友可以参考下
    2015-10-10
  • Java实现线性表的顺序存储

    Java实现线性表的顺序存储

    这篇文章主要为大家详细介绍了Java实现线性表的顺序存储,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10
  • 解读System.getProperty("ENM_HOME")中的值从哪获取的

    解读System.getProperty("ENM_HOME")中的值从哪获取的

    这篇文章主要介绍了解读System.getProperty("ENM_HOME")中的值从哪获取的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12

最新评论