狀態模式:允許對象在內部狀態改變時改變它的行爲,對象看起來好像是修改了它的類
類圖本質上和策略模式一樣
差別就在於策略模式偏重於外部或者是對象本身對行爲的改變,而狀態模式是在於對象內部隨着時間的變化,事件的發生,對象狀態發生變化後而導致的行爲發生變化
更加簡單的說,策略模式偏向於主動改變行爲,而狀態模式偏向於被動改變行爲
改自《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