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区间值判断[10,20)的实现

    JAVA区间值判断[10,20)的实现

    本文主要介绍了JAVA区间值判断[10,20)的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-09-09
  • MyBatis游标Cursor在Oracle数据库上的测试方式

    MyBatis游标Cursor在Oracle数据库上的测试方式

    这篇文章主要介绍了MyBatis游标Cursor在Oracle数据库上的测试方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 四种引用类型在JAVA Springboot中的使用详解

    四种引用类型在JAVA Springboot中的使用详解

    这篇文章主要介绍了springboot的四种引用类型,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Netty分布式FastThreadLocal的set方法实现逻辑剖析

    Netty分布式FastThreadLocal的set方法实现逻辑剖析

    这篇文章主要为大家介绍了Netty分布式FastThreadLocal的set方法实现逻辑剖析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • java多线程中的生产者和消费者队列详解

    java多线程中的生产者和消费者队列详解

    这篇文章主要介绍了java多线程中的生产者和消费者队列详解,队列,是一种数据结构,除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的,需要的朋友可以参考下
    2024-01-01
  • 深入dom4j使用selectSingleNode方法报错分析

    深入dom4j使用selectSingleNode方法报错分析

    本篇文章是对dom4j使用selectSingleNode方法报错进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • SpringBoot 使用 Maven 打包方式

    SpringBoot 使用 Maven 打包方式

    maven打包有三种方式 pom、jar、war,本篇文章给大家介绍SpringBoot 使用 Maven 打包方式,结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2023-10-10
  • SpringBoot开发存储服务器实现过程详解

    SpringBoot开发存储服务器实现过程详解

    这篇文章主要为大家介绍了SpringBoot开发存储服务器实现过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Java数据库连接池的几种配置方法(以MySQL数据库为例)

    Java数据库连接池的几种配置方法(以MySQL数据库为例)

    这篇文章主要介绍了Java数据库连接池的几种配置方法(以MySQL数据库为例) 的相关资料,需要的朋友可以参考下
    2016-07-07
  • SpringBoot 多Profile使用与切换方式

    SpringBoot 多Profile使用与切换方式

    这篇文章主要介绍了SpringBoot 多Profile使用与切换方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04

最新评论