状态模式:当一个对象的内在状态改变时改变其行为,这个对象看起来像是改变了其类。
怎么理解这句话呢,就是说利用状态模式,我们将对象的每个状态封装为各个类,那么对象状态的变化就是其各个状态类之间的切换。
我的理解像除了用于多分枝情况外,更像是有限状态机一样,适用于业务逻辑是枚举类型。
我们要实现一个接口,这个接口就是对象本来的有很多分支实现的功能
public interface State {
void WriteProgram(Work work);
}
然后来看下对象:
public class Work {
private State current;
private double hour;
private boolean finished = false;
public Work() {
current = new ForenoonState();
}
public void setHour(double h) {
hour = h;
}
public double getHour() {
return hour;
}
public void setCurrent(State s) {
current = s;
}
public void writeProgram() {
current.WriteProgram(this);
}
public boolean getTaskState() {
return finished;
}
public void setTaskState(boolean f) {
finished = f;
}
}
通过setHour(double h)来变更状态条件,current.WriteProgram(this)来调用每个状态对应的方法,那么对于Current状态的切换是如何实现的呢?
最开始new work的时候,由于work的构造函数,所以work刚开始的状态就是ForenoonState():
public class ForenoonState implements State {
@Override
public void WriteProgram(Work work) {
if(work.getHour() < 12) {
System.out.println("当前时间:" + work.getHour() + " 上午工作,精神百倍");
}
else {
work.setCurrent(new NoonState());
work.writeProgram();
}
}
}
看到没有,在ForenoonState 判断状态条件,并且用work.setCurrent(new NoonState())更新work对象的状态为NoonState(),并调用下个状态NoonState()状态的方法writeProgram();
接下来都是一样的思路,前一个状态判断应该走哪个分支:
public class NoonState implements State {
@Override
public void WriteProgram(Work work) {
if(work.getHour() < 13) {
System.out.println("当前时间:" + work.getHour() + " 饿了,午饭,犯困,午休。");
}
else {
work.setCurrent(new AfternoonState());
work.writeProgram();
}
}
}
public class AfternoonState implements State {
@Override
public void WriteProgram(Work work) {
if(work.getHour() < 17) {
System.out.println("当前时间:" + work.getHour() + " 下午状态不错,继续努力!");
}
else {
work.setCurrent(new EveningState());
work.writeProgram();
}
}
}
public class EveningState implements State {
@Override
public void WriteProgram(Work work) {
if(work.getTaskState()) {
work.setCurrent(new RestState());
work.writeProgram();
}
else {
if(work.getHour() < 21) {
System.out.println("当前时间:" + work.getHour() + " 加班哦,疲惫至极!");
}
else {
work.setCurrent(new SleepingState());
work.writeProgram();
}
}
}
}
public class RestState implements State {
@Override
public void WriteProgram(Work work) {
System.out.print("当前时间:" + work.getHour() + " 下班回家!!");
}
}
public class SleepingState implements State {
@Override
public void WriteProgram(Work work) {
System.out.println("当前时间:" + work.getHour() + " 不行了,睡着了");
}
}
主函数代码:
Work emergencyProject = new Work();
emergencyProject.setHour(9);
emergencyProject.writeProgram();
emergencyProject.setHour(10);
emergencyProject.writeProgram();
emergencyProject.setHour(12);
emergencyProject.writeProgram();
emergencyProject.setHour(13);
emergencyProject.writeProgram();
emergencyProject.setHour(14);
emergencyProject.writeProgram();
emergencyProject.setHour(17);
emergencyProject.writeProgram();
emergencyProject.setTaskState(false);
emergencyProject.setHour(19);
emergencyProject.writeProgram();
emergencyProject.setHour(22);
emergencyProject.writeProgram();
这种模式带来的好处是,业务状态作为对象就不依赖于其他业务状态了,如果需求变更,那么我们只需要去修改相应装态类。比如添加删除一个分支,只需要增加删除一个类并在前面状态分支类中的判断进行修改就行了。
我思考了下:甚至整个逻辑变化都没事,因为要实现的功能已经被你分割成一个个状态;
逻辑的变化只是对这些状态的重新组合罢了,相对修改起来就比较方便了。
对于对分支的应用场景我理解的是,对于同级的判断状态模式不好用,比如说:
if(1 == a) {
}
else if(2 == a) {
}
else if(3 == a) {
}
这种情况还不如放一个类里判断,既然同级,处理过程就不会有影响。
而对于往深度再判断的,用状态模式就比较好了:
if(1 == a) {
if(1 == b) {
if(1 == c) {
}
}
else if(2 == b) {
if(2 == c) {
}
}
}
你看,这样就是从a=1状态切到b=1或者2状态再切到c对应状态。只需要对每种状态进行编程。这是我理解的状态模式试用的场景。