16.設計模式之狀態模式

1. 定義:

    狀態模式,又稱狀態對象模式(Pattern of Objects for States),狀態模式是對象的行爲模式。
    狀態模式允許一個對象在其內部狀態改變的時候改變其行爲。這個對象看上去就像是改變了它的類一樣

2.例子:

   例子參考HeadFirst  通過狀態模式實現糖果機,糖果機分爲四個狀態:投幣,未投幣,售完,銷售中

   然後通過當前狀態決定當前的操作,看一下,未用狀態模式實現的java代碼

  

public class GumballMachine {
	//糖果機有四種狀態,分別爲:投幣 、未投幣 、售磬、銷售中
	private static int has_money=0;
	private static int no_money=1;
	private static int no_goods=3;
	private static int solding=4;
	
	int state=solding;
	int count=0;
	
	public GumballMachine(int count) {
		this.count=count;
		if(count >0){
			state = no_money;
		}
	}
	//四種操作
	//投幣
	//退錢
	//轉動曲柄
	public void insertMoney(){
		if(state == has_money){
			System.out.println("已經投過幣了");
		}else if(state == no_money){
			state=has_money;
			System.out.println("投入了硬幣");
		}else if(state == no_goods){
			System.out.println("不能投幣,因爲沒有商口了");
		}else if(state == solding){
			System.out.println("稍等一下");
		}
	}
	public void ejectMoney(){
		if(state == has_money){
			System.out.println("退幣了");
			state = no_money;
		}else if(state == no_money){
			System.out.println("沒投幣,退不了");
		}else if(state == solding){
			System.out.println("剛退了");
		}else if(state == no_goods){
			System.out.println("就不給你退");
		}
	}
	public void turnHandler(){
		if(state == solding){
			System.out.println("騙子");
		}else if(state == no_money){
			System.out.println("先投幣");
		}else if(state == no_goods){
			System.out.println("沒有商口");
		}else if(state == has_money){
			System.out.println("給你");
			state=solding;
			dispense();
		}
	}
	public void dispense(){
		if(state == solding){
			System.out.println("稍等");
			count--;
			if(count == 0){
				System.out.println("賣完了");
				state = no_goods;
			}else{
				state = no_money;
			}
		}else if(state == no_money){
			System.out.println("先投幣");
		}else if(state == no_goods){
			System.out.println("沒有商口");
		}else if(state == has_money){
			System.out.println("給你");
			state=solding;
			dispense();
		}
	}
}

 如果只是這四種狀態,這個是沒有問題,但是再添加一種狀態的時候,會發現每一個方法都要改,會造成  代碼特別不容易維護。這個時候就用到了狀態模式,把狀態抽象成一個接口,然後,針對每一種狀態有一個實現類。

看一下類圖結構:



 

通過類圖,我們重寫上面的代碼。

首先是一個State接口:

/**
 * 狀態接口
 * @author king
 *
 */
public interface State {
	public void insertMoney();
	public void ejectMoney();
	public void turnHandler();
	public void dispense();
	
}

 

2. 沒有投幣的實現類

public class NoMoneyState implements State{

	GumballMachine machine;
	public NoMoneyState(GumballMachine machine) {
		this.machine = machine;
	}
	@Override
	public void insertMoney() {
		System.out.println("投入了一個硬幣");
		machine.setDefaultState(machine.getHasMoneyState());
	}
	@Override
	public void ejectMoney() {
		System.out.println("沒有投幣");
	}

	@Override
	public void turnHandler() {
		System.out.println("沒有錢,不能轉");
	}

	@Override
	public void dispense() {
		System.out.println("投幣");
	}
}

 3.銷售狀態的實現類

public class SoldingState implements State{

	GumballMachine machine;
	public SoldingState(GumballMachine machine) {
		this.machine = machine;
	}
	@Override
	public void insertMoney() {
		System.out.println("等會再投");
	}
	@Override
	public void ejectMoney() {
		System.out.println("退不了了");
	}

	@Override
	public void turnHandler() {
		System.out.println("轉動沒用的");
	}

	@Override
	public void dispense() {
		machine.releaseBall();
		if(machine.getCount()>0){
			machine.setDefaultState(machine.getNoMoneyState());
		}else{
			machine.setDefaultState(machine.getNoGoodsState());
		}
	}

}

 

4. 我們看一下銷售機做了哪些便化

public class GumballMachine {
	
	private State noMoneyState;
	private State hasMoneyState;
	private State soldingState;
	private State noGoodsState;
	State defaultState = soldingState;
	int count=0;
	public State getNoMoneyState() {
		return noMoneyState;
	}
	public void setNoMoneyState(State noMoneyState) {
		this.noMoneyState = noMoneyState;
	}
	public State getHasMoneyState() {
		return hasMoneyState;
	}
	public void setHasMoneyState(State hasMoneyState) {
		this.hasMoneyState = hasMoneyState;
	}
	public State getSoldingState() {
		return soldingState;
	}
	public void setSoldingState(State soldingState) {
		this.soldingState = soldingState;
	}
	public State getNoGoodsState() {
		return noGoodsState;
	}
	public void setNoGoodsState(State noGoodsState) {
		this.noGoodsState = noGoodsState;
	}
	public State getDefaultState() {
		return defaultState;
	}
	public void setDefaultState(State defaultState) {
		this.defaultState = defaultState;
	}
	
	public GumballMachine(int count) {
		noMoneyState = new NoMoneyState(this);
		noGoodsState = new NoGoodsState(this);
		hasMoneyState = new HasMoneyState(this);
		soldingState = new SoldingState(this);
		this.count = count;
		if(this.count>0){
			defaultState = noMoneyState;
		}
	}
	
	void releaseBall(){
		System.out.println("出糖");
		if(count!=0){
			count--;
		}
	}
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
	
	public void insertMoney(){
		defaultState.insertMoney();
	}
	public void ejectMoney(){
		defaultState.ejectMoney();
	}
	public void turnHandler(){
		defaultState.turnHandler();
		defaultState.dispense();
	}

}

 

這就是狀態模式