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

什么是状态模式呢?

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

让我们来举个例子




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

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


可乐售货机类:


/**
 * 
 * 可乐自动贩售机类
 * @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、代码中包含大量与对象状态有关的条件语句







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值