状态模式
本篇是《HeaderFirst设计模式》读书笔记。
状态模式定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
不知道你看了定义有啥感悟没,反正我看了是不知道在说啥。下面从实际例子出发
我们要制作一个糖果机。糖果机的控制器的工作如下图:
我们把这张图的每个圆圈看成一个状态,每个箭头看成状态的转换。所以根据图片,我们能找到的四个状态:没有25美分、有25美分、糖果售罄、售出糖果;改变状态的动作:投入25分钱、退回25分钱、转动曲柄、发放糖果。没一个动作都会造成糖果机状态的改变。
在这里我们使用一个通用技巧:如何对对象内的状态建模——通过创建一个实例变量来持有状态值,并在方法内书写条件代码来处理不同状态。
糖果机代码编写:
我们利用实例变量来持有当前的状态,然后需要处理所有可能发生的动作、行为和状态的转换。
public class GumballMachine {
// 每一个状态都用一个不同的整数代表
final static int SALD_OUT = 0,
NO_QUARTER = 1,
HAS_QUARTER = 2,
SOLD = 3;
// 持有当前的状态。因为糖果机一开始拆箱并安装的时候是没有糖果的,所以我们将它设为“糖果售罄”状态
int state = SALD_OUT;
// 追踪糖果机内的糖果数目
int count = 0;
public GumballMachine(int count) {
this.count = count;
// 如果糖果数量大于0,进入“没有硬币”状态
if(count > 0) state = NO_QUARTER;
}
// 投入硬币
public void insertQuarter() {
if(state == SALD_OUT) {
System.out.println("You can't insert a quarter, the machine is sold out.");
} else if(state == NO_QUARTER) {
state = HAS_QUARTER;
System.out.println("you inserted a quarter");
} else if(state == HAS_QUARTER) {
System.out.println("You can't insert another quarter");
} else if(state == SOLD) {
// 如果顾客刚刚才买了糖果,就需要稍等一下,好让状态转换完毕,回复到“没有硬币”的状态
System.out.println("Please wait, we're already giving you a gumball");
}
}
// 退回硬币
public void ejectQuarter() {
if(state == SALD_OUT) {
System.out.println("You can't eject, you haven't inserted a quarter yet");
} else if(state == NO_QUARTER) {
System.out.println("You haven't inserted a quarter");
} else if(state == HAS_QUARTER) {
state = NO_QUARTER;
System.out.println("Quarter returned");
} else if(state == SOLD) {
System.out.println("Sorry, you already turned the crank");
}
}
// 转动曲柄
public void turnCrank() {
if(state == SALD_OUT) {
System.out.println("You turned, but there are no gumballs");
} else if(state == NO_QUARTER) {
System.out.println(