状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像是修改了它的类
类图本质上和策略模式一样
差别就在于策略模式偏重于外部或者是对象本身对行为的改变,而状态模式是在于对象内部随着时间的变化,事件的发生,对象状态发生变化后而导致的行为发生变化
更加简单的说,策略模式偏向于主动改变行为,而状态模式偏向于被动改变行为
改自《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