设计模式学习笔记之状态模式
Posted birdlove1987
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式学习笔记之状态模式相关的知识,希望对你有一定的参考价值。
什么是状态模式呢?
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。。。是不是听起来显示在内部进行零件调换的感觉,其实是有点类似这种想法的,只不过调换的零件就是封装好的状态。
让我们来举个例子
在我还上学的时候,寝室楼下有一台这样的自动贩售机,专门卖饮料。每天晚上寝室关门之后口渴了,在这里面买点饮料喝喝还是很方便的。
下面用程序来模拟一下这个售货机:
可乐售货机类:
/**
*
* 可乐自动贩售机类
* @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;
@Override
public void insertCoin()
// TODO Auto-generated method stub
System.out.println("投币成功,请按出货按钮!");
mVendingMachine.setState(mVendingMachine.mHasCoin);
@Override
public void returnCoin()
// TODO Auto-generated method stub
System.out.println("您还没有投币!");
@Override
public void pressButton()
// TODO Auto-generated method stub
System.out.println("请您先投币!");
@Override
public void appearCola()
// TODO Auto-generated method stub
@Override
public void printState()
// TODO Auto-generated method stub
System.out.println("=========售卖中=========");
/***
* 售空状态类
* @author birdlove1987
*
*/
public class SoldOutState implements State
private VendingMachine mVendingMachine;
public SoldOutState(VendingMachine mCandyMachine)
this.mVendingMachine=mVendingMachine;
@Override
public void insertCoin()
// TODO Auto-generated method stub
System.out.println("请不要投币了,售货机里已经没有可乐了!");
@Override
public void returnCoin()
// TODO Auto-generated method stub
System.out
.println("您还没有投币!");
@Override
public void pressButton()
// TODO Auto-generated method stub
System.out.println("对不起,可乐已售空!");
@Override
public void appearCola()
// TODO Auto-generated method stub
@Override
public void printState()
// TODO Auto-generated method stub
System.out.println("=========售空=========");
/***
* 已投币状态类
* @author birdlove1987
*
*/
public class HasCoin implements State
private VendingMachine mVendingMachine;
public HasCoin(VendingMachine mVendingMachine)
this.mVendingMachine = mVendingMachine;
@Override
public void insertCoin()
// TODO Auto-generated method stub
System.out.println("售货机里以及有硬币了,请勿重复投币!");
@Override
public void returnCoin()
// TODO Auto-generated method stub
System.out.println("请在退币口收好您的硬币");
mVendingMachine.setState(mVendingMachine.mOnReadyState);
@Override
public void pressButton()
// TODO Auto-generated method stub
System.out.println("请稍等,出可乐中!");
//创建随机中奖概率
Random anotherOne = new Random();
//20%的机会再来一瓶
int luck = anotherOne.nextInt(5);
if(luck==0)
mVendingMachine.setState(mVendingMachine.mOneMoreCola);
else
mVendingMachine.setState(mVendingMachine.mSoldState);
@Override
public void appearCola()
@Override
public void printState()
// TODO Auto-generated method stub
System.out.println("=========已投币=========");
/**
* 出可乐状态类
* @author birdlove1987
*
*/
public class SoldState implements State
private VendingMachine mVendingMachine;
public SoldState(VendingMachine mVendingMachine)
this.mVendingMachine=mVendingMachine;
@Override
public void insertCoin()
// TODO Auto-generated method stub
System.out.println("正在出货请勿投币!");
@Override
public void returnCoin()
// TODO Auto-generated method stub
System.out.println("可乐已售出,不能退币");
@Override
public void pressButton()
// TODO Auto-generated method stub
System.out
.println("可乐已出,如想再次购买请再次投币!");
@Override
public void appearCola()
// TODO Auto-generated method stub
mVendingMachine.appearCola();
if (mVendingMachine.getCount() > 0)
mVendingMachine.setState(mVendingMachine.mOnReadyState);
else
System.out.println("对不起,可乐已经售空了,请勿在投币!");
mVendingMachine.setState(mVendingMachine.mSoldOutState);
@Override
public void printState()
// TODO Auto-generated method stub
System.out.println("=========出货中=========");
/***
* 再来一瓶类
* @author birdlove1987
*
*/
public class OneMoreCola implements State
private VendingMachine mVendingMachine;
public OneMoreCola(VendingMachine mVendingMachine)
this.mVendingMachine = mVendingMachine;
@Override
public void insertCoin()
// TODO Auto-generated method stub
System.out.println("正在出货请勿投币!");
@Override
public void returnCoin()
// TODO Auto-generated method stub
System.out.println("可乐已售出,不能退币");
@Override
public void pressButton()
// TODO Auto-generated method stub
System.out.println("请稍等,出可乐中!");
@Override
public void appearCola()
// TODO Auto-generated method stub
mVendingMachine.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);
@Override
public void printState()
// TODO Auto-generated method stub
System.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 stub
if (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、代码中包含大量与对象状态有关的条件语句。
以上是关于设计模式学习笔记之状态模式的主要内容,如果未能解决你的问题,请参考以下文章