状态模式就是用来把多种条件的判断解耦,消除掉if-else或者switch语句。
核心思想是创建基类定义每种条件要实现的抽象方法,然后拓展子类去实现,在子类中如果符合本条件则做出具体操作,如果不符就传递下去。这样添加或者删除分支只需要新建子类,然后至多修改两个上下子类即可。
比如一个判断块:
public void showState(Work work) {
if (work.time < 12) {
System.out.println("早上时间" + work.time + "点");
} else if (work.time < 14) {
System.out.println("午休时间" + work.time + "点");
} else if (work.time < 18) {
System.out.println("下午时间" + work.time + "点");
} else {
System.out.println("下班时间" + work.time + "点");
}
}
这个时候我们就可以抽象出一个状态类IState,供子类实现,Work是条件类:
public interface IState {
void showState(Work work);
}
因为判断条件是按分支传递的,所以可以从最后一个分支倒推上去:
class LeisureState implements IState {
@Override
public void showState(Work work) {
System.out.println("休息时间" + work.time + "点");
}
}
class AfternoonState implements IState {
@Override
public void showState(Work work) {
if (work.time < 18) {
System.out.println("下午" + work.time + "点");
} else {
work.setState(new LeisureState());
work.showState();
}
}
}
class NoonState implements IState {
@Override
public void showState(Work work) {
if (work.time < 14) {
System.out.println("中午" + work.time + "点");
} else {
work.setState(new AfternoonState());
work.showState();
}
}
}
class MorningState implements IState {
@Override
public void showState(Work work) {
if (work.time < 12) {
System.out.println("上午" + work.time + "点");
} else {
work.setState(new NoonState());
work.showState();
}
}
}
重点是条件类:
public class Work {
int time;
IState state;
public Work() {
state = new MorningState();
}
public void setState(IState state) {
this.state = state;
}
public void showState() {
state.showState(this);
}
}
条件类有两个成员变量,一个是所要判断的标准,比如本例中的time。另一个是分支的引用对象,每个分支是独立的,需要使用条件类去调用才能串联起来。初始化条件类的时候可以设置一个分支提供判断。
这样每个分支如果符合条件直接自己执行实现,如果不符合则更新条件类中的具体分支,再去调用分支实现。比如:
class AfternoonState implements IState {
@Override
public void showState(Work work) {
if (work.time < 18) { // 符合本分支条件,直接执行
System.out.println("下午" + work.time + "点");
} else { // 不符合本分支条件,更新条件类当前分支为下一分支并执行
work.setState(new LeisureState());
work.showState();
}
}
}
测试类:
public static void main(String[] args) {
final Work work = new Work();
work.time = 21;
work.showState();
final Work work2 = new Work();
work2.time = 11;
work2.showState();
final Work work3 = new Work();
work3.time = 13;
work3.showState();
final Work work4 = new Work();
work4.time = 16;
work4.showState();
}
输出:
休息时间21点
上午11点
中午13点
下午16点