设计模式学习笔记之状态模式

来源:互联网 发布:linux expect scp 编辑:程序博客网 时间:2024/05/16 07:53

什么是状态模式呢?

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。。。是不是听起来显示在内部进行零件调换的感觉,其实是有点类似这种想法的,只不过调换的零件就是封装好的状态。

让我们来举个例子




在我还上学的时候,寝室楼下有一台这样的自动贩售机,专门卖饮料。每天晚上寝室关门之后口渴了,在这里面买点饮料喝喝还是很方便的。

下面用程序来模拟一下这个售货机:


可乐售货机类:


/** *  * 可乐自动贩售机类 * @author birdlove1987 * */public class VendingMachine {//售空final static int SoldOutState = 0;//在售final static int OnReadyState = 1;//有币final static int HasCoin = 2;//出货final static int SoldState = 3;//售货机状态private int state = SoldOutState;//机内可乐数量private int count = 0;//构造函数,初始化自动贩售机public VendingMachine(int count) {this.count = count;if (count > 0) {state = OnReadyState;}}//向贩售机投币函数public void insertCoin(){switch (state){case SoldOutState:System.out.println("请不要投币了,售货机里已经没有可乐了!");break;case OnReadyState:state = HasCoin;System.out.println("投币成功,请按出货按钮!");break;case HasCoin:System.out.println("售货机里以及有硬币了,请勿重复投币!");break;case SoldState:System.out.println("正在出货请勿投币!");break;}}//贩售机退币函数public void returnCoin() {switch (state){case SoldOutState:System.out.println("您还没有投币!");break;case OnReadyState:System.out.println("您还没有投币!");break;case HasCoin:System.out.println("请在退币口收好您的硬币");state = OnReadyState;break;case SoldState:System.out.println("可乐已售出,不能退币");break;}}//按出可乐按钮函数public void pressButton() {switch (state) {case SoldOutState:System.out.println("对不起,可乐已售空!");break;case OnReadyState:System.out.println("请您先投币!");break;case HasCoin:System.out.println("请稍等,出可乐中!");state = SoldState;appearCola();break;case SoldState:System.out.println("可乐已出,如想再次购买请再次投币!");break;}}//售货机出可乐函数private void appearCola() {count = count - 1;System.out.println("出货口,滚出了一瓶可乐!");if (count > 0){state = OnReadyState;} else{System.out.println("对不起,可乐已经售空了,请勿在投币!");state = SoldOutState;}}//打印目前售货机的状态public void printState() {switch (state) {case SoldOutState:System.out.println("=========售空=========");break;case OnReadyState:System.out.println("=========售卖中=========");break;case HasCoin:System.out.println("=========已投币=========");break;case SoldState:System.out.println("=========出货中=========");break;}}}


写个测试类来测试一下

测试类


/** * 测试类 * @author birdlove1987 * */public class MainTest {public static void main(String[] args) {//创建售货机实例,并且只放入一瓶可乐VendingMachine mVendingMachine=new VendingMachine(1);//打印售货机状态mVendingMachine.printState();//投币mVendingMachine.insertCoin();//打印售货机状态mVendingMachine.printState();//按出货按钮mVendingMachine.pressButton();//打印售货机状态mVendingMachine.printState();//投币mVendingMachine.insertCoin();//打印售货机状态mVendingMachine.printState();//按出货按钮mVendingMachine.pressButton();//打印售货机状态mVendingMachine.printState();}}



嗯!模拟成功了!好像感觉还不错呢!不过买了一段时间,你可能发现,如果不搞一些促销活动,更本就搞不过那些有促销的商家!




所以自动售货机也要搞一个“再来一瓶”的活动啊!

但是!!!如果现在直接在自动售货机的类上去直接修改,就违背了软件设计里的“开-闭原则”了,破坏了我们已经闭合的类。所以现在看来,这种设计并不好。。

下面就轮到状态设计模式登场啦,我们从新构建类,这次以状态为类,来构建。

首先定义一下状态接口


/*** * 状态接口 * @author birdlove1987 * */public interface State {//投币函数public void insertCoin();//退币函数public void returnCoin();//按出可乐按钮函数public void pressButton();//出可乐函数public void appearCola();//打印状态函数public void printState();}


再来定义状态类


/*** * 在售状态类 * @author birdlove1987 * */public class OnReadyState implements State {//贩售机引用private VendingMachine mVendingMachine;//构造函数初始化public OnReadyState(VendingMachine mVendingMachine){this.mVendingMachine=mVendingMachine;}@Overridepublic void insertCoin() {// TODO Auto-generated method stubSystem.out.println("投币成功,请按出货按钮!");mVendingMachine.setState(mVendingMachine.mHasCoin);}@Overridepublic void returnCoin() {// TODO Auto-generated method stubSystem.out.println("您还没有投币!");}@Overridepublic void pressButton() {// TODO Auto-generated method stubSystem.out.println("请您先投币!");}@Overridepublic void appearCola() {// TODO Auto-generated method stub}@Overridepublic void printState() {// TODO Auto-generated method stubSystem.out.println("=========售卖中=========");}}/*** * 售空状态类 * @author birdlove1987 * */public class SoldOutState implements State {private VendingMachine mVendingMachine;public SoldOutState(VendingMachine mCandyMachine){this.mVendingMachine=mVendingMachine;}@Overridepublic void insertCoin() {// TODO Auto-generated method stubSystem.out.println("请不要投币了,售货机里已经没有可乐了!");}@Overridepublic void returnCoin() {// TODO Auto-generated method stubSystem.out.println("您还没有投币!");}@Overridepublic void pressButton() {// TODO Auto-generated method stubSystem.out.println("对不起,可乐已售空!");}@Overridepublic void appearCola() {// TODO Auto-generated method stub}@Overridepublic void printState() {// TODO Auto-generated method stubSystem.out.println("=========售空=========");}}/*** * 已投币状态类 * @author birdlove1987 * */public class HasCoin implements State {private VendingMachine mVendingMachine;public HasCoin(VendingMachine mVendingMachine) {this.mVendingMachine = mVendingMachine;}@Overridepublic void insertCoin() {// TODO Auto-generated method stubSystem.out.println("售货机里以及有硬币了,请勿重复投币!");}@Overridepublic void returnCoin(){// TODO Auto-generated method stubSystem.out.println("请在退币口收好您的硬币");mVendingMachine.setState(mVendingMachine.mOnReadyState);}@Overridepublic void pressButton(){// TODO Auto-generated method stubSystem.out.println("请稍等,出可乐中!");//创建随机中奖概率Random anotherOne = new Random();//20%的机会再来一瓶int luck = anotherOne.nextInt(5);if(luck==0){mVendingMachine.setState(mVendingMachine.mOneMoreCola);}else{mVendingMachine.setState(mVendingMachine.mSoldState);}}@Overridepublic void appearCola(){}@Overridepublic void printState() {// TODO Auto-generated method stubSystem.out.println("=========已投币=========");}}/** * 出可乐状态类 * @author birdlove1987 * */public class SoldState implements State {private VendingMachine mVendingMachine;public SoldState(VendingMachine mVendingMachine){this.mVendingMachine=mVendingMachine;}@Overridepublic void insertCoin() {// TODO Auto-generated method stubSystem.out.println("正在出货请勿投币!");}@Overridepublic void returnCoin() {// TODO Auto-generated method stubSystem.out.println("可乐已售出,不能退币");}@Overridepublic void pressButton(){// TODO Auto-generated method stubSystem.out.println("可乐已出,如想再次购买请再次投币!");}@Overridepublic void appearCola() {// TODO Auto-generated method stubmVendingMachine.appearCola();if (mVendingMachine.getCount() > 0) {mVendingMachine.setState(mVendingMachine.mOnReadyState);}else {System.out.println("对不起,可乐已经售空了,请勿在投币!");mVendingMachine.setState(mVendingMachine.mSoldOutState);}}@Overridepublic void printState(){// TODO Auto-generated method stubSystem.out.println("=========出货中=========");}}/*** * 再来一瓶类 * @author birdlove1987 * */public class OneMoreCola implements State {private VendingMachine mVendingMachine;public OneMoreCola(VendingMachine mVendingMachine) {this.mVendingMachine = mVendingMachine;}@Overridepublic void insertCoin() {// TODO Auto-generated method stubSystem.out.println("正在出货请勿投币!");}@Overridepublic void returnCoin() {// TODO Auto-generated method stubSystem.out.println("可乐已售出,不能退币");}@Overridepublic void pressButton() {// TODO Auto-generated method stubSystem.out.println("请稍等,出可乐中!");}@Overridepublic void appearCola() {// TODO Auto-generated method stubmVendingMachine.appearCola();if (mVendingMachine.getCount() == 0) {mVendingMachine.setState(mVendingMachine.mSoldOutState);} else {System.out.println("恭喜你获得了再来一瓶,马上为您再出一瓶可乐");mVendingMachine.appearCola();if (mVendingMachine.getCount() > 0) {mVendingMachine.setState(mVendingMachine.mOnReadyState);}else {System.out.println("对不起,可乐已经售空了,请勿在投币!");mVendingMachine.setState(mVendingMachine.mSoldOutState);}}}@Overridepublic void printState() {// TODO Auto-generated method stubSystem.out.println("=========再来一瓶=========");}}


构建自动贩售机类


/** * 自动售货机类 * @author birdlove1987 * */public class VendingMachine {//状态类引用State mSoldOutState;State mOnReadyState;State mHasCoin;State mSoldState;State mOneMoreCola;//目前状态private State state;//可乐计数器private int count = 0;//构造函数public VendingMachine(int count) {this.count = count;mSoldOutState = new SoldOutState(this);mOnReadyState = new OnReadyState(this);mHasCoin = new HasCoin(this);mSoldState = new SoldState(this);mOneMoreCola = new OneMoreCola(this);if (count > 0) {state = mOnReadyState;}else {state = mSoldOutState;}}//设置状态函数public void setState(State state) {this.state = state;}//投币函数public void insertCoin() {state.insertCoin();}//退币函数public void returnCoin() {state.returnCoin();}//按出可乐按钮函数public void pressButton() {state.pressButton();state.appearCola();}//出可乐函数void appearCola() {// TODO Auto-generated method stubif (count > 0){count = count - 1;System.out.println("出货口,滚出了一瓶可乐!");}}//可乐计数函数public int getCount() {return count;}//打印状态函数public void printState() {state.printState();}}


最后写一个测试类测试一下


/** * 测试类 * @author birdlove1987 * */public class MainTest {public static void main(String[] args) {//实例化自动贩售机对象VendingMachine mVendingMachine = new VendingMachine(10);//打印状态mVendingMachine.printState();//投币mVendingMachine.insertCoin();//打印状态mVendingMachine.printState();//按出可乐按钮mVendingMachine.pressButton();//打印状态mVendingMachine.printState();//投币mVendingMachine.insertCoin();//打印状态mVendingMachine.printState();//按出可乐按钮mVendingMachine.pressButton();//打印状态mVendingMachine.printState();}}




卧槽!一次都没中奖,什么鬼!!!不行,买买买!!!




中了一次。。。好吧,我来作弊一下。。调到100%




哈哈哈!


状态模式的优点
    1.状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
    2.将与状态有关的行为封装到一个类中,方便地增加新的状态,只需改变对象状态即可改变对象的行为。 
    3.提供代码复用性,降低了程序的某些耦合性。   
     
状态模式的缺点
    1.有时候状态类会很多,而且逻辑复杂。

状态模式适用场景
    1、对象的行为依赖于它的状态,并且其行为依据它的状态改变而改变。 
    2、代码中包含大量与对象状态有关的条件语句







1 0