状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像是修改了它的类
类图本质上和策略模式一样
差别就在于策略模式偏重于外部或者是对象本身对行为的改变,而状态模式是在于对象内部随着时间的变化,事件的发生,对象状态发生变化后而导致的行为发生变化
更加简单的说,策略模式偏向于主动改变行为,而状态模式偏向于被动改变行为
改自《Head First》课后:糖果贩卖机
代码实现:
public abstract class State { public void putMoney() { System.out.println("Error state, can't put money"); } public void backMoney() { System.out.println("Error state, can't back money"); } public boolean turnHandle() { System.out.println("Error state, turn handle no effect"); return false; } public void provideSugar() { System.out.println("Error state, can't provide sugar"); } public void refillSugar() { System.out.println("Error state, can't refill sugar"); } }
public class NoMoneyState extends State { private SugarMachine machine; public NoMoneyState(SugarMachine sugarMachine) { machine = sugarMachine; } @Override public void putMoney() { System.out.println("Put money"); machine.setState(machine.getHasMoneyState()); } }
public class HasMoneyState extends State { private SugarMachine machine; public HasMoneyState(SugarMachine sugarMachine) { machine = sugarMachine; } @Override public void backMoney() { System.out.println("Money back"); machine.setState(machine.getNoMoneyState()); } @Override public boolean turnHandle() { int random = new Random(System.currentTimeMillis()).nextInt(10); if (random == 0 && machine.getCount() > 1) { machine.setState(machine.getWinnerState()); return true; } else { machine.setState(machine.getSoldState()); return true; } } }
public class SoldState extends State { private SugarMachine machine; public SoldState(SugarMachine sugarMachine) { machine = sugarMachine; } @Override public void provideSugar() { machine.releaseSugar(); if (machine.getCount() > 0) { machine.setState(machine.getNoMoneyState()); } else { System.out.println("Sugar is sold out"); machine.setState(machine.getSoldOutState()); } } }
public class WinnerState extends State { private SugarMachine machine; public WinnerState(SugarMachine sugarMachine) { machine = sugarMachine; } @Override public void provideSugar() { System.out.println("You are winner, you can get two sugars"); machine.releaseSugar(); if (machine.getCount() == 0) { machine.setState(machine.getSoldOutState()); } else { machine.releaseSugar(); if (machine.getCount() > 0) { machine.setState(machine.getNoMoneyState()); } else { System.out.println("Sugar is sold out"); machine.setState(machine.getSoldOutState()); } } } }
public class SoldOutState extends State { private SugarMachine machine; public SoldOutState(SugarMachine sugarMachine) { machine = sugarMachine; } @Override public void refillSugar() { System.out.println("Sugar is refilled again"); machine.setState(machine.getNoMoneyState()); } }
public class SugarMachine { private State noMoneyState; private State hasMoneyState; private State soldOutState; private State winnerState; private State soldState; private State state; private int count; public SugarMachine(int numberOfSuagr) { count = numberOfSuagr; this.noMoneyState = new NoMoneyState(this); this.hasMoneyState = new HasMoneyState(this); this.soldState = new SoldState(this); this.winnerState = new WinnerState(this); this.soldOutState = new SoldOutState(this); this.state = soldOutState; if (count > 0) { this.state = noMoneyState; } } public void setState(State state) { this.state = state; } public void putMoney() { state.putMoney(); } public void backMoney() { state.backMoney(); } public void turnHandle() { if (state.turnHandle()) { state.provideSugar(); } } public void refillSugar(int count) { this.count += count; state.refillSugar(); } public void releaseSugar() { System.out.println("A sugar is rolling out"); if (count > 0) { count--; } } public State getNoMoneyState() { return noMoneyState; } public State getHasMoneyState() { return hasMoneyState; } public State getSoldOutState() { return soldOutState; } public State getWinnerState() { return winnerState; } public State getSoldState() { return soldState; } public int getCount() { return count; } }
public class PatternDemo { public static void main(String[] args) { SugarMachine machine = new SugarMachine(3); machine.backMoney(); machine.turnHandle(); machine.putMoney(); machine.backMoney(); //1 machine.putMoney(); machine.turnHandle(); machine.turnHandle(); //2 machine.putMoney(); machine.putMoney(); machine.turnHandle(); //3 machine.putMoney(); machine.turnHandle(); //4 machine.putMoney(); machine.turnHandle(); machine.refillSugar(1); //5 machine.putMoney(); machine.turnHandle(); } }
Error state, can't back money
Error state, turn handle no effect
Put money
Money back
Put money
A sugar is rolling out
Error state, turn handle no effect
Put money
Error state, can't put money
A sugar is rolling out
Put money
A sugar is rolling out
Sugar is sold out
Error state, can't put money
Error state, turn handle no effect
Sugar is refilled again
Put money
A sugar is rolling out
Sugar is sold out