23种设计模式:10状态模式

it2024-11-06  8

允许一个对象在其内部状态改变时改变它的行为,让对象看起来似乎修改了它的类

介绍

状态模式中主要有2个类,分别是Work和State,今天我们利用工作的状态来理解状态模式,比如,我们在工作的时候,根据时间的不同,有以下几种状态。

12点之前:精神百倍12 - 13点:饿了,午饭:犯困,午休13 - 17点:下午状态还不错,继续努力17 - 21点:可能加班,也可能被强制回家21点之后:不行了,睡着了。 上面的场景,我们可以看出,我们的工作状态和时间有关(或者被强制回家)。 所以,我们希望设计一个State类,这个State类代表工作中的时间状态,同时,它可以根据不同的时间状态修改Work的其他状态。 这种当一个对象的内在状态改变时允许改变类的行为,我们称为状态模式。也就是说,Work的行为和State有关。

UML图

状态模式的UML图可能有些复杂,可以结合代码理解

Work类

work类中有3个属性:

current:代表当前的状态,这个状态会随hour改变而改变hour:时间,也就是引起变化的原因finish:这个不用太关注,也就另外一个引起变化的原因的例子

writeProgram()方法:

它的作用是,当current发生变化时,通知State接口的子类,让符合要求的State的子类来改变Work的行为
State接口:

下面有6个实现类,实现的方式都差不多,也就不一一介绍了,它的作用是,根据Work的时间状态,从ForenoonState开始判断(途中的虚线箭头),如果找到满足当前时间的状态,就用当前的类,去修改Work的状态;比如途中的NoonState类。 这种回调的修改状态的方式,简化了Work类的逻辑,可以让他专注与自生的业务逻辑,State的子类虽然多了,但是它减少了一系列的if else 的判断语句,也就让逻辑判断更加清晰了

代码

如果上面的原理明白了,代码也就很简单了,如果还不懂,敲一遍代码也对理解状态模式是一个很好的帮助。

Work类 public class Work { private State current;//当前状态 private double hour;//时间 private boolean finish = false;//结束 public Work(){ current = new ForenoonState(); } public double getHour() { return hour; } public void setHour(double hour) { this.hour = hour; } public boolean getFinish() { return finish; } public void setFinish(boolean finish) { this.finish = finish; } public State getCurrent() { return current; } public void setCurrent(State current) { this.current = current; } public void writeProgram(){ current.writeProgram(this); } } State接口 public abstract class State { public abstract void writeProgram(Work w); } 下面是State的子类,逻辑都差不多 public class ForenoonState extends State{ @Override public void writeProgram(Work w) { if(w.getHour() < 12){ System.out.println("当前时间:" + w.getHour() + "点 上午工作,精神百倍"); } else { w.setCurrent(new NoonState()); w.writeProgram(); } } } public class NoonState extends State{ @Override public void writeProgram(Work w) { if(w.getHour() < 13){ System.out.println("当前时间:" + w.getHour() + "点 饿了,午饭:犯困,午休。"); } else { w.setCurrent(new AfternoonState()); w.writeProgram(); } } } public class AfternoonState extends State { @Override public void writeProgram(Work w) { if(w.getHour() < 17){ System.out.println("当前时间:" + w.getHour() + "点 下午状态还不错,继续努力。"); } else { w.setCurrent(new EveningState()); w.writeProgram(); } } } public class EveningState extends State { @Override public void writeProgram(Work w) { if(w.getFinish()){ w.setCurrent(new RestState()); w.writeProgram(); } else{ if(w.getHour() < 21){ System.out.println("当前时间:" +w.getHour()+ "点 加班哦,疲惫之极"); } else { w.setCurrent(new SleepingState()); w.writeProgram(); } } } } public class RestState extends State { @Override public void writeProgram(Work w) { System.out.println("当前时间:" + w.getHour() + "点下班回家了。"); } } public class SleepingState extends State { @Override public void writeProgram(Work w) { System.out.println("当前时间:" + w.getHour() + "点 不行了,睡着了。"); } } 使用方式,和打印结果 public class Demo { public static void main(String[] args) { Work emergencyProjects = new Work(); emergencyProjects.setHour(9); emergencyProjects.writeProgram(); emergencyProjects.setHour(10); emergencyProjects.writeProgram(); emergencyProjects.setHour(12); emergencyProjects.writeProgram(); emergencyProjects.setHour(13); emergencyProjects.writeProgram(); emergencyProjects.setHour(14); emergencyProjects.writeProgram(); emergencyProjects.setHour(17); emergencyProjects.setFinish(false); emergencyProjects.writeProgram(); emergencyProjects.setHour(19); emergencyProjects.writeProgram(); emergencyProjects.setHour(22); emergencyProjects.writeProgram(); } } 当前时间:9.0点 上午工作,精神百倍 当前时间:10.0点 上午工作,精神百倍 当前时间:12.0点 饿了,午饭:犯困,午休。 当前时间:13.0点 下午状态还不错,继续努力。 当前时间:14.0点 下午状态还不错,继续努力。 当前时间:17.0点 加班哦,疲惫之极 当前时间:19.0点 加班哦,疲惫之极 当前时间:22.0点 不行了,睡着了。

总结

状态模式主要是将逻辑判断非常多的情况下,将每个逻辑判断分拆成不同的类,这样有助于后期的代码维护和他人对代码的逻辑的理解。如果后期业务逻辑有修改,修改或增加单个判断,也不会影响其他的逻辑判断但如果业务的逻辑判断并不多,也就不必要用状态模式了
最新回复(0)