tuniumobile 2018-07-04
本例使用状态机演示一个自动售货机的使用场景。
状态机接口:
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 糖果已售光,请不要投币! 糖果已售光,请不要转动摇柄! 尚未投币!
整体流程字符流 -> 状态机 -> 词token -> 栈 -> dom构建 DOM 的过程是:从父到子,从先到后,一个一个节点构造,并且挂载到DOM树上。<p class="a">text text