16.设计模式之状态模式

1. 定义:

    状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式。
    状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样

2.例子:

   例子参考HeadFirst  通过状态模式实现糖果机,糖果机分为四个状态:投币,未投币,售完,销售中

   然后通过当前状态决定当前的操作,看一下,未用状态模式实现的java代码

  

public class GumballMachine {
	//糖果机有四种状态,分别为:投币 、未投币 、售磬、销售中
	private static int has_money=0;
	private static int no_money=1;
	private static int no_goods=3;
	private static int solding=4;
	
	int state=solding;
	int count=0;
	
	public GumballMachine(int count) {
		this.count=count;
		if(count >0){
			state = no_money;
		}
	}
	//四种操作
	//投币
	//退钱
	//转动曲柄
	public void insertMoney(){
		if(state == has_money){
			System.out.println("已经投过币了");
		}else if(state == no_money){
			state=has_money;
			System.out.println("投入了硬币");
		}else if(state == no_goods){
			System.out.println("不能投币,因为没有商口了");
		}else if(state == solding){
			System.out.println("稍等一下");
		}
	}
	public void ejectMoney(){
		if(state == has_money){
			System.out.println("退币了");
			state = no_money;
		}else if(state == no_money){
			System.out.println("没投币,退不了");
		}else if(state == solding){
			System.out.println("刚退了");
		}else if(state == no_goods){
			System.out.println("就不给你退");
		}
	}
	public void turnHandler(){
		if(state == solding){
			System.out.println("骗子");
		}else if(state == no_money){
			System.out.println("先投币");
		}else if(state == no_goods){
			System.out.println("没有商口");
		}else if(state == has_money){
			System.out.println("给你");
			state=solding;
			dispense();
		}
	}
	public void dispense(){
		if(state == solding){
			System.out.println("稍等");
			count--;
			if(count == 0){
				System.out.println("卖完了");
				state = no_goods;
			}else{
				state = no_money;
			}
		}else if(state == no_money){
			System.out.println("先投币");
		}else if(state == no_goods){
			System.out.println("没有商口");
		}else if(state == has_money){
			System.out.println("给你");
			state=solding;
			dispense();
		}
	}
}

 如果只是这四种状态,这个是没有问题,但是再添加一种状态的时候,会发现每一个方法都要改,会造成  代码特别不容易维护。这个时候就用到了状态模式,把状态抽象成一个接口,然后,针对每一种状态有一个实现类。

看一下类图结构:



 

通过类图,我们重写上面的代码。

首先是一个State接口:

/**
 * 状态接口
 * @author king
 *
 */
public interface State {
	public void insertMoney();
	public void ejectMoney();
	public void turnHandler();
	public void dispense();
	
}

 

2. 没有投币的实现类

public class NoMoneyState implements State{

	GumballMachine machine;
	public NoMoneyState(GumballMachine machine) {
		this.machine = machine;
	}
	@Override
	public void insertMoney() {
		System.out.println("投入了一个硬币");
		machine.setDefaultState(machine.getHasMoneyState());
	}
	@Override
	public void ejectMoney() {
		System.out.println("没有投币");
	}

	@Override
	public void turnHandler() {
		System.out.println("没有钱,不能转");
	}

	@Override
	public void dispense() {
		System.out.println("投币");
	}
}

 3.销售状态的实现类

public class SoldingState implements State{

	GumballMachine machine;
	public SoldingState(GumballMachine machine) {
		this.machine = machine;
	}
	@Override
	public void insertMoney() {
		System.out.println("等会再投");
	}
	@Override
	public void ejectMoney() {
		System.out.println("退不了了");
	}

	@Override
	public void turnHandler() {
		System.out.println("转动没用的");
	}

	@Override
	public void dispense() {
		machine.releaseBall();
		if(machine.getCount()>0){
			machine.setDefaultState(machine.getNoMoneyState());
		}else{
			machine.setDefaultState(machine.getNoGoodsState());
		}
	}

}

 

4. 我们看一下销售机做了哪些便化

public class GumballMachine {
	
	private State noMoneyState;
	private State hasMoneyState;
	private State soldingState;
	private State noGoodsState;
	State defaultState = soldingState;
	int count=0;
	public State getNoMoneyState() {
		return noMoneyState;
	}
	public void setNoMoneyState(State noMoneyState) {
		this.noMoneyState = noMoneyState;
	}
	public State getHasMoneyState() {
		return hasMoneyState;
	}
	public void setHasMoneyState(State hasMoneyState) {
		this.hasMoneyState = hasMoneyState;
	}
	public State getSoldingState() {
		return soldingState;
	}
	public void setSoldingState(State soldingState) {
		this.soldingState = soldingState;
	}
	public State getNoGoodsState() {
		return noGoodsState;
	}
	public void setNoGoodsState(State noGoodsState) {
		this.noGoodsState = noGoodsState;
	}
	public State getDefaultState() {
		return defaultState;
	}
	public void setDefaultState(State defaultState) {
		this.defaultState = defaultState;
	}
	
	public GumballMachine(int count) {
		noMoneyState = new NoMoneyState(this);
		noGoodsState = new NoGoodsState(this);
		hasMoneyState = new HasMoneyState(this);
		soldingState = new SoldingState(this);
		this.count = count;
		if(this.count>0){
			defaultState = noMoneyState;
		}
	}
	
	void releaseBall(){
		System.out.println("出糖");
		if(count!=0){
			count--;
		}
	}
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
	
	public void insertMoney(){
		defaultState.insertMoney();
	}
	public void ejectMoney(){
		defaultState.ejectMoney();
	}
	public void turnHandler(){
		defaultState.turnHandler();
		defaultState.dispense();
	}

}

 

这就是状态模式