Neumann 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