欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

状态模式(形式一)

程序员文章站 2022-06-17 17:10:26
...

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

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

状态模式(形式一)状态模式(形式一)

使用原始的方法:在糖果机里面定义对应的状态(属性)以及行为(方法),然后在方法执行的时候,用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:除了在糖果机类声明所有状态的引用,以及构造函数赋值,还有其它的方法吗?

相关标签: 状态模式