publicclassCandyMachine{finalstaticintSoldOutState=0;// 初始状态finalstaticintOnReadyState=1;// 待机状态finalstaticintHasCoin=2;// 准备状态finalstaticintSoldState=3;// 售出状态privateintstate=SoldOutState;// 变量,用于存放当前的状态值privateintcount;// 糖果的数目publicCandyMachine(intcount){this.count=count;if(count>0){state=OnReadyState;}}// 投入硬币行为的时候,通过判断当前的状态来匹配所有的状态.publicvoidinsertCoin(){switch(state){caseSoldOutState:System.out.println("you can't insert coin,the machine sold out!");break;caseOnReadyState:// 只有在待机状态的时候,投入硬币行为正确,并将状态改变为准备状态state=HasCoin;System.out.println("you have inserted a coin,next,please turn crank!");break;caseHasCoin:System.out.println("you can't insert another coin!");break;caseSoldState:System.out.println("please wait!we are giving you a candy!");break;}}// 回退硬币publicvoidreturnCoin(){switch(state){caseSoldOutState:System.out.println("you can't return,you haven't inserted a coin yet!");break;caseOnReadyState:System.out.println("you haven't inserted a coin yet!");break;caseHasCoin:System.out.println("coin return!");state=OnReadyState;break;caseSoldState:System.out.println("sorry,you already have turned the crank!");break;}}// 转动曲柄publicvoidturnCrank(){switch(state){caseSoldOutState:System.out.println("you turned,but there are no candies!");break;caseOnReadyState:System.out.println("you turned,but you haven't inserted a coin!");break;caseHasCoin:System.out.println("crank turn...!");state=SoldState;dispense();break;caseSoldState:System.out.println("we are giving you a candy,turning another get nothing,!");break;}}// 触发发放糖果行为privatevoiddispense(){count=count-1;System.out.println("a candy rolling out!");if(count>0){state=OnReadyState;}else{System.out.println("Oo,out of candies");state=SoldOutState;}}publicvoidprintstate(){switch(state){caseSoldOutState:System.out.println("***SoldOutState***");break;caseOnReadyState:System.out.println("***OnReadyState***");break;caseHasCoin:System.out.println("***HasCoin***");break;caseSoldState:System.out.println("***SoldState***");break;}}}
那么上面这种方式存在什么问题呢?首先很直观的感受就是:
存在大量的 switch case 语句 当然可以用 if else 也是一样的;
可扩展性差,并且一旦要加入一种新的状态,那么就会要修改所有的 switch case 不符合开闭原则;
publicclassOnReadyStateimplementsState{privateCandyMachinemCandyMachine;publicOnReadyState(CandyMachinemCandyMachine){this.mCandyMachine=mCandyMachine;}@OverridepublicvoidinsertCoin(){System.out.println("you have inserted a coin,next,please turn crank!");mCandyMachine.setState(mCandyMachine.mHasCoin);}@OverridepublicvoidreturnCoin(){System.out.println("you haven't inserted a coin yet!");}@OverridepublicvoidturnCrank(){System.out.println("you turned,but you haven't inserted a coin!");}@Overridepublicvoiddispense(){}@Overridepublicvoidprintstate(){System.out.println("***OnReadyState***");}}
publicclassSoldOutStateimplementsState{privateCandyMachinemCandyMachine;publicSoldOutState(CandyMachinemCandyMachine){this.mCandyMachine=mCandyMachine;}@OverridepublicvoidinsertCoin(){System.out.println("you can't insert coin,the machine sold out!");}@OverridepublicvoidreturnCoin(){System.out.println("you can't return,you haven't inserted a coin yet!");}@OverridepublicvoidturnCrank(){System.out.println("you turned,but there are no candies!");}@Overridepublicvoiddispense(){}@Overridepublicvoidprintstate(){System.out.println("***SoldOutState***");}}
publicclassSoldStateimplementsState{privateCandyMachinemCandyMachine;publicSoldState(CandyMachinemCandyMachine){this.mCandyMachine=mCandyMachine;}@OverridepublicvoidinsertCoin(){System.out.println("please wait!we are giving you a candy!");}@OverridepublicvoidreturnCoin(){System.out.println("you haven't inserted a coin yet!");}@OverridepublicvoidturnCrank(){System.out.println("we are giving you a candy,turning another get nothing,!");}@Overridepublicvoiddispense(){mCandyMachine.releaseCandy();if(mCandyMachine.getCount()>0){mCandyMachine.setState(mCandyMachine.mOnReadyState);}else{System.out.println("Oo,out of candies");mCandyMachine.setState(mCandyMachine.mSoldOutState);}}@Overridepublicvoidprintstate(){System.out.println("***SoldState***");}}
publicclassWinnerStateimplementsState{privateCandyMachinemCandyMachine;publicWinnerState(CandyMachinemCandyMachine){this.mCandyMachine=mCandyMachine;}@OverridepublicvoidinsertCoin(){System.out.println("please wait!we are giving you a candy!");}@OverridepublicvoidreturnCoin(){System.out.println("you haven't inserted a coin yet!");}@OverridepublicvoidturnCrank(){System.out.println("we are giving you a candy,turning another get nothing,!");}@Overridepublicvoiddispense(){mCandyMachine.releaseCandy();if(mCandyMachine.getCount()==0){mCandyMachine.setState(mCandyMachine.mSoldOutState);}else{System.out.println("you are a winner!you get another candy!");mCandyMachine.releaseCandy();if(mCandyMachine.getCount()>0){mCandyMachine.setState(mCandyMachine.mOnReadyState);}else{System.out.println("Oo,out of candies");mCandyMachine.setState(mCandyMachine.mSoldOutState);}}}@Overridepublicvoidprintstate(){System.out.println("***WinnerState***");}}
publicclassCandyMachine{StatemSoldOutState;StatemOnReadyState;StatemHasCoin;StatemSoldState;StatemWinnerState;privateStatestate;privateintcount;publicCandyMachine(intcount){this.count=count;mSoldOutState=newSoldOutState(this);mOnReadyState=newOnReadyState(this);mHasCoin=newHasCoin(this);mSoldState=newSoldState(this);mWinnerState=newWinnerState(this);if(count>0){state=mOnReadyState;}else{state=mSoldOutState;}}publicvoidsetState(Statestate){this.state=state;}publicvoidinsertCoin(){state.insertCoin();}publicvoidreturnCoin(){state.returnCoin();}publicvoidturnCrank(){state.turnCrank();state.dispense();}voidreleaseCandy(){if(count>0){count=count-1;System.out.println("a candy rolling out!");}}publicintgetCount(){returncount;}publicvoidprintstate(){state.printstate();}}