状态模式(形式一)

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

例子:糖果机,有多种状态以及多种行为,每种状态执行每种行为会得到不同的结果,并转向下一个不同的状态。

使用原始的方法:在糖果机里面定义对应的状态(属性)以及行为(方法),然后在方法执行的时候,用if...else...判断当前状态,然后执行不同的逻辑代码。

弊端:不易于扩展,当添加新的状态以及行为时,需要在糖果机里面新增属性以及方法,还要修改之前方法里的代码。

talk is cheap show me the code

首先定义状态接口,包含所有的行为

public interface State {

	// 投入25分钱
	void insertQuarter();
	
	// 退回25分钱
	void ejectQuarter();
	
	// 转动曲柄
	void turnCrank();
	
	// 发放糖果
	void dispense();
}

然后定义一个抽象类,实现状态接口,并提供糖果机的引用以及所有方法的默认实现

public abstract class AbstractState implements State {

	protected GumballMachine gumballMachine;
	
	public AbstractState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	
	@Override
	public void insertQuarter() {
		throw new UnsupportedOperationException();
	}

	@Override
	public void ejectQuarter() {
		throw new UnsupportedOperationException();
	}

	@Override
	public void turnCrank() {
		throw new UnsupportedOperationException();
	}

	@Override
	public void dispense() {
		throw new UnsupportedOperationException();
	}

}

接下来写所有的状态实现类

/**
 * 没有25分钱
 * @author z_hh
 * @time 2018年7月22日
 */
public class NoQuarterState extends AbstractState {

	public NoQuarterState(GumballMachine gumballMachine) {
		super(gumballMachine);
	}

	@Override
	public void insertQuarter() {
		System.out.println("You insert a quarter");
		gumballMachine.setState(gumballMachine.getHasQuarterState());
	}

	@Override
	public void ejectQuarter() {
		System.out.println("You haven't inserted a quarter");
	}

	@Override
	public void turnCrank() {
		System.err.println("You turned, but there's no quarter");
	}

	@Override
	public void dispense() {
		System.out.println("You need to pay first");
	}

}
/**
 * 有25分钱
 * @author z_hh
 * @time 2018年7月22日
 */
public class HasQuarterState extends AbstractState {

	public HasQuarterState(GumballMachine gumballMachine) {
		super(gumballMachine);
	}

	@Override
	public void insertQuarter() {
		System.out.println("You can't insert another quarter");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("Quarter returned");
		gumballMachine.setState(gumballMachine.getNoQuarterState());
	}

	@Override
	public void turnCrank() {
		System.out.println("You turned...");
		gumballMachine.setState(gumballMachine.getSoldState());
	}

	@Override
	public void dispense() {
		System.out.println("No gumball dispensed");
	}

}
/**
 * 售出糖果
 * @author z_hh
 * @time 2018年7月22日
 */
public class SoldState extends AbstractState {

	public SoldState(GumballMachine gumballMachine) {
		super(gumballMachine);
	}

	@Override
	public void insertQuarter() {
		System.out.println("Please wait, we're already giving you a gumball");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("Sorry, you already turned the crank");
	}

	@Override
	public void turnCrank() {
		System.out.println("Turning twice doesn't get you another gumball");
	}

	@Override
	public void dispense() {
		gumballMachine.releaseBall();
		if (gumballMachine.getCount() > 0) {
			gumballMachine.setState(gumballMachine.getNoQuarterState());
		} else {
			System.out.println("Oops, out of gumballs");
			gumballMachine.setState(gumballMachine.getSoldOutState());
		}
	}

}
/**
 * 糖果售罄
 * @author z_hh
 * @time 2018年7月22日
 */
public class SoldOutState extends AbstractState {

	public SoldOutState(GumballMachine gumballMachine) {
		super(gumballMachine);
	}

	@Override
	public void insertQuarter() {
		System.out.println("You can't insert a quarter, the machine is sole out");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("You can't eject, you haven't inserted a quarter yet");
	}

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

	@Override
	public void dispense() {
		System.out.println("No gumball dispensed");
	}

}

最后写糖果机的代码

public class GumballMachine {

	private State soldOutState;
	
	private State noQuarterState;
	
	private State hasQuarterState;
	
	private State soldState;
	
	private State state = soldOutState;
	
	private int count = 0;
	
	public GumballMachine(int numberGumball) {
		soldOutState = new SoldOutState(this);
		noQuarterState = new NoQuarterState(this);
		hasQuarterState = new HasQuarterState(this);
		soldState = new SoldState(this);
		
		this.count = numberGumball;
		if (count > 0) {
			state = noQuarterState;
		}
	}
	
	public void insertQuarter() {
		state.insertQuarter();
	}

	public void ejectQuarter() {
		state.ejectQuarter();
	}
	
	public void turnCrank() {
		state.turnCrank();
		state.dispense();
	}
	
	void setState(State state) {
		this.state = state;
	}
	
	void releaseBall() {
		System.out.println("A gumball comes rolling out the slot...");
		if (count != 0) {
			count--;
		}
	}
	
	public State getState() {
		return state;
	}
	
	public State getSoldOutState() {
		return soldOutState;
	}
	
	public State getNoQuarterState() {
		return noQuarterState;
	}
	
	public State getHasQuarterState() {
		return hasQuarterState;
	}
	
	public State getSoldState() {
		return soldState;
	}
	
	public int getCount() {
		return count;
	}

	@Override
	public String toString() {
		return "GumballMachine [state=" + state.getClass().getSimpleName() + ", count=" + count + "]";
	}
	
}

测试:

public class Test {

	public static void main(String[] args) {
		// 创建糖果机,初始化5颗糖
		GumballMachine gumballMachine = new GumballMachine(5);
		
		System.out.println(gumballMachine);

		gumballMachine.insertQuarter();// 投入25分钱
		gumballMachine.turnCrank();// 转动曲柄
		
		System.out.println(gumballMachine);
		
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		
		System.out.println(gumballMachine);
	}

}

结果:

GumballMachine [state=NoQuarterState, count=5]
You insert a quarter
You turned...
A gumball comes rolling out the slot...
GumballMachine [state=NoQuarterState, count=4]
You insert a quarter
You turned...
A gumball comes rolling out the slot...
You insert a quarter
You turned...
A gumball comes rolling out the slot...
GumballMachine [state=NoQuarterState, count=2]

注意:本文案例来自《Head First设计模式》。

问题1:如果新增了状态以及行为,除了这种方案------接口增加方法,所有实现类也对应添加并且实现,新增状态实现类,糖果机增加该类的引用,然后修改每个状态实现类的相关代码。还有其它方法吗?

问题2:除了在糖果机类声明所有状态的引用,以及构造函数赋值,还有其它的方法吗?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值