【设计模式】《Head First 设计模式》读书笔记——状态模式

状态模式:

允许对象在内部状态改变时改变它的行为,对象看起来好想修改了它的类。

问题简单描述:

需要实现一个糖果自动售货机。原先的售货机状态转化如下:

后需求变动添加了10%概率双倍糖果的赢家状态,状态转化如下:

原先的静态状态量表示状态,大段if else代码完成状态转化难以扩展代码需要重构。

解决思路:

创建状态接口,包含所有引起状态改变的事件处理的方法,将每种状态单独封装成类,继承状态接口,分别实现每种事件的处理方法。

UML图:





实现代码:

state接口

package state;

public abstract class State {

	/**
	 * 投入硬币
	 */
	public void insertQuarter(){
		System.out.println("please wait,we will give you a gumball soon");
	}
	
	/**
	 * 退币
	 */
	public void ejectQuarter(){
		System.out.println("can't eject quarter");
	}
	
	/**
	 * 转动曲柄
	 */
	public void turnCrank(){
		System.out.println("sorry,you have turned the crank");
	}
	
	/**
	 * 发糖
	 */
	public void dispense(){
		System.out.println("you have to insert quarter");
	}

}

具体state类

package state;

/**
 * 无硬币状态
 * @author terry
 *
 */
public class NoQuarterState extends State {
	
	GumballMachine gumballMachine;
	
	public NoQuarterState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	/**
	 * 重写塞入硬币方法,塞入硬币后进入有硬币状态
	 */
	public void insertQuarter(){
		System.out.println("insert quarter");
		gumballMachine.setState(gumballMachine.getHasQuarterState());
	}
	
	public void turnCrank(){
		System.out.println("you have to insert quarter");
	}

}
package state;

import java.util.Random;

/**
 * 有硬币状态
 * @author terry
 *
 */
public class HasQuarterState extends State{
	
	GumballMachine gumballMachine;
	
	Random randomWinner=new Random(System.currentTimeMillis());

	public HasQuarterState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	
	/**
	 * 重写转动曲柄,机器进去售卖状态或胜者状态
	 */
	public void turnCrank(){
		System.out.println("you turned……");
		int winner = randomWinner.nextInt(10);
		if(winner==0&&(gumballMachine.getCount()>1)){
			gumballMachine.setState(gumballMachine.getWinnerState());
		}else{
			gumballMachine.setState(gumballMachine.getSoldState());
		}
	}
	
	/**
	 * 重写退回硬币,硬币退回,机器回到无硬币状态
	 */
	public void ejectQuarter(){
		System.out.println("eject quarter");
		gumballMachine.setState(gumballMachine.getNoQuarterState());
	}
	
}
package state;

/**
 * 销售状态
 * @author terry
 *
 */
public class SoldState extends State {
	
	GumballMachine gumballMachine;
	
	public SoldState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	/**
	 * 重写发糖方法,机器发糖,发完糖如果还有糖变成无硬币状态,否则变成售完状态
	 */
	public void dispense(){
		gumballMachine.releaseBall();
		if(gumballMachine.getCount()>0){
			gumballMachine.setState(gumballMachine.getNoQuarterState());
		}else{
			gumballMachine.setState(gumballMachine.getSoldOutState());
		}
	}

}
package state;

/**
 * 售罄状态
 * @author terry
 *
 */
public class SoldOutState extends State{
	
	GumballMachine gumballMachine;

	public SoldOutState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	
	/**
	 * 重写塞硬币状态
	 */
	public void insertQuarter(){
		System.out.println("sold out! eject quarter");
	}
	
	public void turnCrank(){
		System.out.println("sold out! please wait");
	}
	
	

}
package state;

/**
 * 获胜状态
 * 
 * @author terry
 * 
 */
public class WinnerState extends State {

	GumballMachine gumballMachine;

	public WinnerState(GumballMachine gumballMachine) {
		super();
		this.gumballMachine = gumballMachine;
	}

	/**
	 * 重写发糖方法,机器发两颗糖,发完糖如果还有糖变成无硬币状态,否则变成售完状态
	 */
	public void dispense() {
		System.out.println("conguratulation ! you are a winner!");
		gumballMachine.releaseBall();
		if (gumballMachine.getCount() > 0) {
			gumballMachine.releaseBall();
			if (gumballMachine.getCount() > 0) {
				gumballMachine.setState(gumballMachine.getNoQuarterState());
			} else {
				gumballMachine.setState(gumballMachine.getSoldOutState());
			}
		} else {
			gumballMachine.setState(gumballMachine.getSoldOutState());
		}
	}

}

售货机类(Context)

package state;

/**
 * 糖果机
 * @author terry
 *
 */
public class GumballMachine {
	
	NoQuarterState noQuarterState;
	HasQuarterState hasQuarterState;
	SoldState soldState;
	SoldOutState soldOutState;
	WinnerState winnerState;
	
	State state;
	
	int count=0;
	
	/**
	 * 初始化时添加糖果
	 * @param count
	 */
	public GumballMachine(int count) {
		noQuarterState=new NoQuarterState(this);
		hasQuarterState=new HasQuarterState(this);
		soldState=new SoldState(this);
		soldOutState=new SoldOutState(this);
		winnerState=new WinnerState(this);
		this.count = count;
		if(count>0){
			state=noQuarterState;
		}else{
			state=soldOutState;
		}
	}

	/**
	 * 机器出糖果
	 */
	public void releaseBall(){
		if(count>0){
			count--;
			System.out.println("A gumball comes rolling out the slot……");
		}
	}
	
	/**
	 * 投入硬币
	 */
	public void insertQuarter(){
		state.insertQuarter();
	}
	
	/**
	 * 退币
	 */
	public void ejectQuarter(){
		state.ejectQuarter();
	}
	
	/**
	 * 转动曲柄
	 */
	public void turnCrank(){
		state.turnCrank();
		if(count>0){
			state.dispense();
		}
	}
	
	
	public NoQuarterState getNoQuarterState() {
		return noQuarterState;
	}

	public void setNoQuarterState(NoQuarterState noQuarterState) {
		this.noQuarterState = noQuarterState;
	}

	public HasQuarterState getHasQuarterState() {
		return hasQuarterState;
	}

	public void setHasQuarterState(HasQuarterState hasQuarterState) {
		this.hasQuarterState = hasQuarterState;
	}
	
	public SoldState getSoldState() {
		return soldState;
	}

	public void setSoldState(SoldState soldState) {
		this.soldState = soldState;
	}
	
	public SoldOutState getSoldOutState() {
		return soldOutState;
	}

	public void setSoldOutState(SoldOutState soldOutState) {
		this.soldOutState = soldOutState;
	}

	public WinnerState getWinnerState() {
		return winnerState;
	}

	public void setWinnerState(WinnerState winnerState) {
		this.winnerState = winnerState;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}
	
	
	
	

}

测试类:

package state;

public class Test {

	public static void main(String[] args) {
		
		GumballMachine gumballMachine=new GumballMachine(3);
		
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		System.out.println("========================================");
		
		gumballMachine.insertQuarter();
		gumballMachine.ejectQuarter();
		System.out.println("========================================");
		
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		System.out.println("========================================");
		
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		System.out.println("========================================");

	}

}

运行结果:


状态模式将不同的状态用不同的类表示,并组合进context中,context将行为委托给当前的状态对象,实现一个对象基于内部状态拥有不同行为。增加了类的数目但是使得可扩展性大大增强。

^ ^欢迎批评指正







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值