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(); } }
這就是狀態模式