设计模式 状态模式 以自动售货机为例(二)

2014-11-23 20:19:57 · 作者: · 浏览: 34
发生了变化,当用户转动手柄时,可能会达到一个中奖的状态:图如下:

\

如果在我们刚写的代码上直接添加,则需要在每个动作的switch中添加判断条件,且非常容易出错。所以现在我们要考虑重新设计我们的代码,我们考虑把每个状态写状态类,负责实现在对应动作下的行为,然后自动售货机在不能的状态间切换:

下面开始重构,我们现在有5种状态,对应4个动作(投币、退币、转动手柄、发出商品),下面首先定义一个状态的超类型:

package com.zhy.pattern.status.b;

/**
 * 状态的接口
 * @author zhy
 *
 */
public interface State
{
	/**
	 * 放钱
	 */
	public void insertMoney();
	/**
	 * 退钱
	 */
	public void backMoney();
	/**
	 * 转动曲柄
	 */
	public void turnCrank();
	/**
	 * 出商品
	 */
	public void dispense();
}

然后分别是每个状态的实现:

package com.zhy.pattern.status.b;

/**
 * 没钱的状态
 * @author zhy
 *
 */
public class NoMoneyState implements State
{

	private VendingMachine machine;

	public NoMoneyState(VendingMachine machine)
	{
		this.machine = machine;
		
	}
	
	@Override
	public void insertMoney()
	{
		System.out.println("投币成功");
		machine.setState(machine.getHasMoneyState());
	}

	@Override
	public void backMoney()
	{
		System.out.println("您未投币,想退钱?...");
	}

	@Override
	public void turnCrank()
	{
		System.out.println("您未投币,想拿东西么?...");
	}

	@Override
	public void dispense()
	{
		throw new IllegalStateException("非法状态!");
	}

}

package com.zhy.pattern.status.b;

import java.util.Random;

/**
 * 已投入钱的状态
 * 
 * @author zhy
 * 
 */
public class HasMoneyState implements State
{

	private VendingMachine machine;
	private Random random = new Random();

	public HasMoneyState(VendingMachine machine)
	{
		this.machine = machine;
	}

	@Override
	public void insertMoney()
	{
		System.out.println("您已经投过币了,无需再投....");
	}

	@Override
	public void backMoney()
	{
		System.out.println("退币成功");

		machine.setState(machine.getNoMoneyState());
	}

	@Override
	public void turnCrank()
	{
		System.out.println("你转动了手柄");
		int winner = random.nextInt(10);
		if (winner == 0 && machine.getCount() > 1)
		{
			machine.setState(machine.getWinnerState());
		} else
		{
			machine.setState(machine.getSoldState());
		}
	}

	@Override
	public void dispense()
	{
		throw new IllegalStateException("非法状态!");
	}

}

package com.zhy.pattern.status.b;

/**
 * 售罄的状态
 * 
 * @author zhy
 * 
 */
public class SoldOutState implements State
{

	private VendingMachine machine;

	public SoldOutState(VendingMachine machine)
	{
		this.machine = machine;
	}

	@Override
	public void insertMoney()
	{
		System.out.println("投币失败,商品已售罄");
	}

	@Override
	public void backMoney()
	{
		System.out.println("您未投币,想退钱么?...");
	}

	@Override
	public void turnCrank()
	{
		System.out.println("商品售罄,转动手柄也木有用");
	}

	@Override
	public void dispense()
	{
		throw new IllegalStateException("非法状态!");
	}

}

package com.zhy.pattern.status.b;

/**
 * 准备出商品的状态,该状态下,不会有任何用户的操作
 * 
 * @author zhy
 * 
 */
public class SoldState implements State
{

	private VendingMachine machine;

	public SoldState(VendingMachine machine)
	{
		this.machine = machine;
	}

	@Override
	public void insertMoney()
	{
		System.out.println("正在出货,请勿投币");
	}

	@Override
	public void backMoney()
	{
		System.out.println("正在出货,没有可退的钱");
	}

	@Override
	public void turnCrank()
	{
		System.out.println("正在出货,请勿重复转动手柄");
	}

	@Override
	public void dispense()
	{
		machine.dispense();
		if (machine.getCount() > 0)
		{
			machine.setState(machine.getNoMoneyState());