1. 程式人生 > >【設計模式】狀態模式

【設計模式】狀態模式

模式定義

狀態模式允許物件在內部狀態改變時改變它的行為,物件看起來好像修改了它的類。

下圖是該模式的類圖:
狀態模式類圖

一個生動的例子

就是一個自動售賣機,投硬幣—>搖桿—>出東西。
一共有這麼幾個狀態:無硬幣狀態、有硬幣狀態、無貨狀態和出貨狀態。
下面是程式碼:

狀態介面:
public interface State {

	// 投硬幣
	void insertQuarter();

	// 退硬幣
	void ejectQuarter();

	// 搖桿
	void turnCrank();

	// 取東西
	void dispense();
}
無硬幣的狀態:
public
class NoQuarterState implements State { private GumballMachine gumballMachine; public NoQuarterState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } @Override public void insertQuarter() { System.out.println("You inserted a quarter."); gumballMachine.setState(
gumballMachine.getHasQuarterState()); } @Override public void ejectQuarter() { System.out.println("You haven't inserted a quarter."); } @Override public void turnCrank() { System.out.println("You turned but there's no quarter."); } @Override public void dispense() { System.out.println
("You need to pay first."); } }
有硬幣的狀態:
public class HasQuarterState implements State {
	private GumballMachine gumballMachine;

	public HasQuarterState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	@Override
	public void insertQuarter() {
		System.out.println("You can't insert another quarter.");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("Quarter returned.");
		gumballMachine.setState(gumballMachine.getNoQuarterState());
	}

	@Override
	public void turnCrank() {
		System.out.println("You turned...");
		gumballMachine.setState(gumballMachine.getSoldState());
		gumballMachine.dispense();
	}

	@Override
	public void dispense() {
		System.out.println("No gumballs dispensed.");
	}
}
出貨狀態:
public class SoldState implements State {
	private GumballMachine gumballMachine;

	public SoldState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	@Override
	public void insertQuarter() {
		System.out.println("Please wait, we're already giving you a gumball.");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("Sorry, you already turned the crank.");
	}

	@Override
	public void turnCrank() {
		System.out.println("Turning twice doesn't get you another gumball!");
	}

	@Override
	public void dispense() {
		gumballMachine.releaseBall();
		if (gumballMachine.getCount() > 0) {
			gumballMachine.setState(gumballMachine.getNoQuarterState());
		} else {
			System.out.println("Oops, out of gumballs!");
			gumballMachine.setState(gumballMachine.getSoldOutState());
		}
	}
}
無貨狀態:
public class SoldOutState implements State {

	@Override
	public void insertQuarter() {
		System.out.println("You can't insert a quarter, the machine is sold out.");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("You can't eject, you haven't inserted a quarter yet.");
	}

	@Override
	public void turnCrank() {
		System.out.println("You turned but there's no gumballs.");
	}

	@Override
	public void dispense() {
		System.out.println("No gumballs dispensed.");
	}
}
售賣機:
public class GumballMachine {
	private State soldOutState;
	private State noQuarterState;
	private State hasQuarterState;
	private State soldState;

	private State state = soldOutState;
	private int count = 0;

	public GumballMachine(int numberGumballs) {
		soldOutState = new SoldOutState();
		noQuarterState = new NoQuarterState(this);
		hasQuarterState = new HasQuarterState(this);
		soldState = new SoldState(this);

		this.count = numberGumballs;
		if (numberGumballs > 0) {
			state = noQuarterState;
		}
	}

	public void insertQuarter() {
		state.insertQuarter();
	}

	public void ejectQuarter() {
		state.ejectQuarter();
	}

	public void turnCrank() {
		state.turnCrank();
	}

	public void dispense() {
		state.dispense();
	}

	public void releaseBall() {
		System.out.println("A gumball comes rolling out the slot...");
		if (count != 0) {
			count = count - 1;
		}
	}

	public State getSoldOutState() {
		return soldOutState;
	}

	public void setSoldOutState(State soldOutState) {
		this.soldOutState = soldOutState;
	}

	public State getNoQuarterState() {
		return noQuarterState;
	}

	public void setNoQuarterState(State noQuarterState) {
		this.noQuarterState = noQuarterState;
	}

	public State getHasQuarterState() {
		return hasQuarterState;
	}

	public void setHasQuarterState(State hasQuarterState) {
		this.hasQuarterState = hasQuarterState;
	}

	public State getSoldState() {
		return soldState;
	}

	public void setSoldState(State soldState) {
		this.soldState = soldState;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	@Override
	public String toString() {
		return "GumballMachine [state=" + state.getClass().getSimpleName() + ", count=" + count + "]";
	}
}

參考

  1. Head First 設計模式[書籍]