`

状态机

 
阅读更多

本例使用状态机演示一个自动售货机的使用场景。

 

状态机接口: 

package statemachine;

/**
 * 状态机接口
 * 
 * @author guweiqiang
 * 2018年7月4日
 */
public interface State {
	
	/**
	 * 定义机器全部动作
	 */
	// 投入硬币
	void insertCoin();
	
	// 退回硬币
	void ejectCoin();
	
	// 转动摇柄
	void turnCrank();
	
	// 喷出糖果
	void dispense();
	
}

 

  

状态机类: 

package statemachine;

/**
 * 状态机类
 * 
 * @author guweiqiang
 * 2018年7月4日
 */
public class Machine {
	
	// 机器包含的所有状态
	private State nonCoinState; // 未投币状态
	private State hasCoinState; // 已投币状态
	private State soldState; // 正在出售状态
	private State soldOutState; // 已售光状态
	
	private State state; // 机器当前状态
	private int count; // 机器中当前的糖果数量
	
	/**
	 * 初始化状态机:引入所有的状态,并初始化糖果数量
	 * @param count
	 */
	public Machine(int count) {
		this.nonCoinState = new NonCoinState(this);
		this.hasCoinState = new HasCoinState(this);
		this.soldState = new SoldState(this);
		this.soldOutState = new SoldOutState(this);
		this.count = count;
		if(this.count>0) {
			this.state = nonCoinState;
		} else {
			this.state = soldOutState;
		}
	}
	
	// 投币
	public void insertCoin() {
		this.state.insertCoin();
	}
	
	// 退回硬币
	public void ejectCoin() {
		this.state.ejectCoin();
	}
	
	// 转动摇柄
	public void turnCrank() {
		this.state.turnCrank();
		this.state.dispense();
	}
	
	// 喷出糖果的内部处理
	public void releaseBall() {
		System.out.println("喷出了1个糖果。");
		if(this.count>0) {
			this.count--;
		}
	}

	// 各个状态的get方法
	public State getNonCoinState() {
		return nonCoinState;
	}

	public State getHasCoinState() {
		return hasCoinState;
	}

	public State getSoldState() {
		return soldState;
	}

	public State getSoldOutState() {
		return soldOutState;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	public int getCount() {
		return count;
	}

}

 

 

 未投币状态类: 

package statemachine;

/**
 * 未投币状态类
 * 
 * @author guweiqiang
 * 2018年7月4日
 */
public class NonCoinState implements State {
	
	private Machine machine;
	
	public NonCoinState(Machine machine) {
		this.machine = machine;
	}

	// 投币
	public void insertCoin() {
		System.out.println("已投入硬币!");
		machine.setState(machine.getHasCoinState());
	}

	// 退回硬币
	public void ejectCoin() {
		System.out.println("没有可退回的硬币!");
	}

	// 转动摇柄
	public void turnCrank() {
		System.out.println("请先投币,再转动摇柄!");
	}

	// 喷出糖果
	public void dispense() {
		System.out.println("尚未投币!");
	}

}

 

 

 已投币状态类: 

package statemachine;

/**
 * 已投币状态类
 * 
 * @author guweiqiang
 * 2018年7月4日
 */
public class HasCoinState implements State {

	private Machine machine;

	public HasCoinState(Machine machine) {
		this.machine = machine;
	}
	
	// 投币
	public void insertCoin() {
		System.out.println("请不要重复投币!");
	}

	// 退回硬币
	public void ejectCoin() {
		System.out.println("已退回硬币!");
		machine.setState(machine.getNonCoinState()); // 重新设置为未投币状态
	}

	// 转动摇柄
	public void turnCrank() {
		System.out.println("转动了摇柄");
		machine.setState(machine.getSoldState()); // 设置机器状态为正在出售
	}

	// 喷出糖果
	public void dispense() {
		System.out.println("请转动摇柄!");
	}

}

 

 

 正在出售状态类: 

package statemachine;

/**
 * 正在出售状态类
 * 
 * @author guweiqiang
 * 2018年7月4日
 */
public class SoldState implements State {
	
	private Machine machine;

	public SoldState(Machine machine) {
		this.machine = machine;
	}
	
	// 投币
	public void insertCoin() {
		System.out.println("请等待,正在出货!");
	}

	// 退回硬币
	public void ejectCoin() {
		System.out.println("正在出货,无法退回硬币!");
	}

	// 转动摇柄
	public void turnCrank() {
		System.out.println("请不要重复转动摇柄!");
	}

	// 喷出糖果
	public void dispense() {
		// 喷出糖果
		machine.releaseBall();
		if(machine.getCount()>0) { // 还有糖果,可以继续出售
			machine.setState(machine.getNonCoinState());
		} else { // 已售光
			machine.setState(machine.getSoldOutState());
		}
	}

}

 

 

 已售光状态类: 

package statemachine;

/**
 * 已售光状态类
 * 
 * @author guweiqiang
 * 2018年7月4日
 */
public class SoldOutState implements State {

	private Machine machine;

	public SoldOutState(Machine machine) {
		this.machine = machine;
	}
	
	// 投币
	public void insertCoin() {
		System.out.println("糖果已售光,请不要投币!");
	}

	// 退回硬币
	public void ejectCoin() {
		System.out.println("没有可退回的硬币!");
	}

	// 转动摇柄
	public void turnCrank() {
		System.out.println("糖果已售光,请不要转动摇柄!");
		machine.setState(machine.getNonCoinState());
	}

	// 喷出糖果
	public void dispense() {
		System.out.println("糖果已售光!");
	}

}

 

  

测试类:

package statemachine;

/**
 * 测试类
 * 
 * @author guweiqiang
 * 2018年7月4日
 */
public class StateMachineTest {

	public static void main(String[] args) {
		Machine machine = new Machine(10);
		for (int i=0; i<12; i++) {
			System.out.println(i+": 当前糖果数量:" + machine.getCount());
			if(i==5) {
				machine.insertCoin();
				machine.ejectCoin();
				continue;
			}
			machine.insertCoin();
			machine.turnCrank();
		}

	}

}

 测试结果:

0: 当前糖果数量:10
已投入硬币!
转动了摇柄
喷出了1个糖果。
1: 当前糖果数量:9
已投入硬币!
转动了摇柄
喷出了1个糖果。
2: 当前糖果数量:8
已投入硬币!
转动了摇柄
喷出了1个糖果。
3: 当前糖果数量:7
已投入硬币!
转动了摇柄
喷出了1个糖果。
4: 当前糖果数量:6
已投入硬币!
转动了摇柄
喷出了1个糖果。
5: 当前糖果数量:5
已投入硬币!
已退回硬币!
6: 当前糖果数量:5
已投入硬币!
转动了摇柄
喷出了1个糖果。
7: 当前糖果数量:4
已投入硬币!
转动了摇柄
喷出了1个糖果。
8: 当前糖果数量:3
已投入硬币!
转动了摇柄
喷出了1个糖果。
9: 当前糖果数量:2
已投入硬币!
转动了摇柄
喷出了1个糖果。
10: 当前糖果数量:1
已投入硬币!
转动了摇柄
喷出了1个糖果。
11: 当前糖果数量:0
糖果已售光,请不要投币!
糖果已售光,请不要转动摇柄!
尚未投币!

 

 

 

 

 

 

分享到:
评论

相关推荐

    单片机裸奔之状态机浅谈

    说到单片机编程,不得不说到状态机,状态机做为软件编程的主要架构已经在各种语言中应用,当然包括C语言,在一个思路清晰而且高效的程序中,必然有状态机的身影浮现。灵活的应用状态机不仅是程序更高效,而且可读性...

    verilog有限状态机实验报告(附源代码).pdf

    verilog有限状态机实验报告(附源代码).pdfverilog有限状态机实验报告(附源代码).pdfverilog有限状态机实验报告(附源代码).pdfverilog有限状态机实验报告(附源代码).pdfverilog有限状态机实验报告(附源代码)....

    SMC - 状态机代码生成工具 - Java工程示例

    1、资源内容:Java工程示例的SMC - 状态机的基本格式说明及使用示例; 2、应用场景:SMC可以通过一个配置文件,生成有限状态机所需的所有状态类以及状态机类,同时还包括了所有的状态间的转换逻辑。 3、参考链接:...

    收集的状态机资料

    同步状态机的原理、结构和设计.ppt 实验三:状态机编程 (1).pdf 实验三:状态机编程.pdf 操作系统课程设计报告-基于时间片的轮转调度算法.doc 时间片轮转法进行CPU调度.doc 时间片轮转法进行CPU调度算法实验....

    VHDL——有限状态机

    有限状态机有限状态机有限状态机有限状态机有限状态机有限状态机

    Labview 状态机 程序框架设计

    在LabVIEW中进行程序框架设计,似乎只见到过一种框架,那就是状态机,(并行的算不算?)还有“主/从设计模式”、“生产/消费模式”之类的,但好像也是建立在状态机的基础上的。如果真是这样的话,状态机就成了唯一...

    基于C语言实现的嵌入式电机状态机(含源码)

    前言 背景 内外事件 事件数据 状态转变 状态机模块 电机实例 外部事件 州数 状态函数 状态图 状态机对象 过渡图 新的状态机步骤 状态引擎 生成事件 不使用堆 离心机测试实例 多线程安全

    StateMachineCompiler for C 根据状态表生成【层次状态机】【C代码】

    Python实现,根据状态表生成C代码的【层次状态机】,亦可退化成【平面状态机】。使用C模拟C++的一些特性。 2009.12.3: 里面有readme,在研究之前先读一下。 对于号称“专业研究。。。”的fazai001(无激发)同学,...

    fpga 状态机 写法

    现在大家比较统一的观点是,状态机的写法应该是用三段式写法,即第一部分说明初始状态,current_state,第二部分是状态机的状态转化的描述,第三部分是每一步状态的组合逻辑的描述。这样写调理更加清晰,也更加利于...

    通用有限状态机(FSM: Finite-state machine)自动代码生成器

    通用有限状态机(FSM: Finite-state machine)自动代码生成器. 可以根据配置文件,自动生成状态机代码(C++)。配置文件中只需要定义状态,跃迁条件。然后完善每个状态的动作即可。省去开发过程中手写状态机的麻烦。...

    fsm_keil_version3_keil有限状态机_fsm打开_8051实现状态机_

    在8051单片机内实现列表型的状态机。如果你需要更多的状态转移,你只需要将任务函数加入到列表里面即可。里面还附带了电路图

    二段式状态机

    二段式状态机,状态转换,还是有毛刺的。

    qt并发状态机应用实例

    qt中,关于并发状态机,满足两个子状态都结束才能向父状态的下一个状态切换的实例,本人亲测有效。 在用qt状态机的时候,往往会遇到一个问题,就是在实际任务执行中,我们不希望两个并行的任务,其中一个结束,就...

    有限状态机VHDL模板

    有限状态机VHDL模板 FPGA开发实用模板

    状态机的使用

    状态机是计算机网络通信的重要内容,想要对tcp-ip协议栈加深了解的朋友尤其需要重点掌握,状态机的使用,统计字符串中单词的个数

    单片机多按键状态机的实现

    通过按键状态机方式实现多个按键扫描,具有短按,长按,释放检测功能

    嵌入式STM32按键状态机-单击双击长按操作

    本程序使用定时器,运用状态机的思想,实现了单按键的单击长按操作。 代码简洁规范,可读性强,移植性强。 实验器材: 自制开发板,STM32F03C8T6平台 实验目的: 学习定时器中断、按键使用。实现单击双击长按操作 ...

    C语言嵌入式状态机架构(含C源码)

    状态机简介 函数指针实现FSM 代码实现步骤 附代码 测试程序 总结

    如何在verdi中直接查看状态机的状态名

    如何在verdi中直接查看状态机的状态名 同样适用于debussy

    管理订单状态,该上状态机吗?轻量级状态机COLA StateMachine保姆级入门教程.doc

    管理订单状态,该上状态机吗?轻量级状态机COLA StateMachine保姆级入门教程.doc

Global site tag (gtag.js) - Google Analytics