设计模式12-状态模式

1.场景问题解决

1.1 场景描述

糖果售卖机,状态有售完0,待机1,已投币2,给糖果3.

1.2 OO设计

  • 糖果售卖机
public class CandyMachine {

	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 CandyMachine(int count) {
		this.count = count;
		if (count > 0) {
			state = OnReadyState;
		}
	}

	public void insertCoin() {
		switch (state) {
		case SoldOutState:
			System.out.println("you can't insert coin,the machine sold out!");
			break;
		case OnReadyState:
			state = HasCoin;
			System.out.println("you have inserted a coin,next,please turn crank!");
			break;
		case HasCoin:
			System.out.println("you can't insert another coin!");

			break;
		case SoldState:
			System.out.println("please wait!we are giving you a candy!");
			break;
		}

	}

	public void returnCoin() {
		switch (state) {
		case SoldOutState:
			System.out.println("you can't return,you haven't inserted a coin yet!");
			break;
		case OnReadyState:
			System.out.println("you haven't inserted a coin yet!");
			break;
		case HasCoin:
			System.out.println("coin return!");
			state = OnReadyState;
			break;
		case SoldState:
			System.out.println("sorry,you already have turned the crank!");
			break;
		}

	}

	public void turnCrank() {
		switch (state) {
		case SoldOutState:
			System.out.println("you turned,but there are no candies!");
			break;
		case OnReadyState:
			System.out.println("you turned,but you haven't inserted a coin!");
			break;
		case HasCoin:
			System.out.println("crank turn...!");
			state = SoldState;
			dispense();
			break;
		case SoldState:
			System.out.println("we are giving you a candy,turning another get nothing,!");
			break;
		}

	}

	private void dispense() {
		count = count - 1;
		System.out.println("a candy rolling out!");
		if (count > 0) {
			state = OnReadyState;
		} else {
			System.out.println("Oo,out of candies");
			state = SoldOutState;
		}
	}

	public void printstate() {
		switch (state) {
		case SoldOutState:
			System.out.println("***SoldOutState***");
			break;
		case OnReadyState:
			System.out.println("***OnReadyState***");
			break;
		case HasCoin:
			System.out.println("***HasCoin***");
			break;
		case SoldState:
			System.out.println("***SoldState***");
			break;
		}
	}
}

  • MainTest 测试类
public class MainTest {
	public static void main(String[] args) {
		CandyMachine mCandyMachine=new CandyMachine(1);
		
		mCandyMachine.printstate();
		
		mCandyMachine.insertCoin();
		mCandyMachine.printstate();
		
		mCandyMachine.turnCrank();
		
		mCandyMachine.printstate();
		
		mCandyMachine.insertCoin();
		mCandyMachine.printstate();
		
		mCandyMachine.turnCrank();
		
		mCandyMachine.printstate();
	}
}

1.3 需求变动

加入游戏元素:有10%的概率可以拿到2粒糖果,会多了一个状态"中奖".

1.4 带来问题

加入一个状态后,状态的组合会增加许多,并且如果修改会修改之前的逻辑,修改代码较多.

2.用设计模式改进

状态改变但是行为不改变,所有可以把状态封装为对象,状态中封装了动作/行为.

2.1 分析

2.2 重新设计

[外链图片转存失败(img-jCbNZuev-1566575835237)(https://github.com/bobshute/public/blob/master/imgs/csdn/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/12%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F-1%E7%B1%BB%E5%9B%BE.png?raw=true)]

2.3 源码

  • interface State
public interface State {
	//插入硬币
	public void insertCoin();
	//返回硬币
	public void returnCoin();
	//转动曲柄
	public void turnCrank();
	//分发糖果
	public void dispense();
	//打印状态
	public void printstate();
}

  • SoldOutState、HasCoin、OnReadyState、SoldState、 WinnerState 各状态实现State接口

public class SoldOutState implements State {
	private CandyMachine mCandyMachine;
	public SoldOutState(CandyMachine mCandyMachine)
	{
		this.mCandyMachine=mCandyMachine;
	}

	@Override
	public void insertCoin() {
		System.out.println("you can't insert coin,the machine sold out!");
	}

	@Override
	public void returnCoin() {
		System.out.println("you can't return,you haven't inserted a coin yet!");
	}

	@Override
	public void turnCrank() {
		System.out.println("you turned,but there are no candies!");
	}

	@Override
	public void dispense() {
	}

	@Override
	public void printstate() {
		System.out.println("***SoldOutState***");
	}
}
  • CandyMachine糖果机

public class CandyMachine {
	State mSoldOutState;
	State mOnReadyState;
	State mHasCoin;
	State mSoldState;
	State mWinnerState;
	private State state;
	private int count = 0;

	public CandyMachine(int count) {
		this.count = count;
		mSoldOutState = new SoldOutState(this);
		mOnReadyState = new OnReadyState(this);
		mHasCoin = new HasCoin(this);
		mSoldState = new SoldState(this);
		mWinnerState = new WinnerState(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 turnCrank() {
		state.turnCrank();
		state.dispense();
	}

	void releaseCandy() {
		if (count > 0) {
			count = count - 1;
			System.out.println("a candy rolling out!");
		}
	}

	public int getCount() {
		return count;
	}

	public void printstate() {
		state.printstate();
	}
}
  • 测试类

public class StateTest {
	public static void main(String[] args) {
		CandyMachine mCandyMachine = new CandyMachine(6);

		mCandyMachine.printstate();

		mCandyMachine.insertCoin();
		mCandyMachine.printstate();

		mCandyMachine.turnCrank();

		mCandyMachine.printstate();

		mCandyMachine.insertCoin();
		mCandyMachine.printstate();

		mCandyMachine.turnCrank();

		mCandyMachine.printstate();
	}
}

3.设计模式总结

3.1 定义

***状态模式***能根据内部状态的变化,改变对象的行为,看起来好像修改了类

3.2 分析思路

状态是可变的,但是行为是固定的.
所以将状态定义为接口可变,接口中有行为是固定的,然后各种具体状态实现该状态接口,在各状态对象中处理各种行为是否可行.
状态对象中对修改的关闭,对功能的扩展.

4. 设计模式使用场景及注意

5.参考文章

内容总计于HeadFirst设计模式及相关视频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值