狀態模式(State Pattern)

狀態模式:允許對象在內部狀態改變時改變它的行爲,對象看起來好像是修改了它的類


類圖本質上和策略模式一樣

差別就在於策略模式偏重於外部或者是對象本身對行爲的改變,而狀態模式是在於對象內部隨着時間的變化,事件的發生,對象狀態發生變化後而導致的行爲發生變化

更加簡單的說,策略模式偏向於主動改變行爲,而狀態模式偏向於被動改變行爲


改自《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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章