本片文章主要介绍状态模式。
状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式只要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同的一系列类当中,可以把复杂的判断逻辑化。当然,如果这个判断很简单,那就没必要使用状态模式。
我们先看下结构图:
State类,抽象状态类,定义一个接口与Context的一个特定状态相关的行为。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:24 */ public interface State { void handle(Context context); }
ConcreteState类,集体状态,每一个子类实现一个与Context的一个状态相关的行为。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:27 */ public class ConcreteStateA implements State { @Override public void handle(Context context) { context.setState(new ConcreteStateB()); } }
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:27 */ public class ConcreteStateB implements State { @Override public void handle(Context context) { context.setState(new ConcreteStateA()); } }
Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:24 */ public class Context { private State state; public Context(State state) { this.state = state; } public State getState() { return state; } public void setState(State state) { this.state = state; System.out.println("当前状态:" + state.getClass().getName()); } public void request() { state.handle(this); } }
然后是测试类和运行结果。
package com.lwx.state; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:29 */ public class Client { public static void main(String[] args) { Context context = new Context(new ConcreteStateA()); context.request(); context.request(); context.request(); context.request(); } }
可以看到我们没调用一次request()方法就会改变一次状态。
上面的例子很简单,结构清晰但是理解起来却很生硬,下面我们用大话设计模式一书中的工作状态例子来展示一下。
我们还是先看下结构图:
首先是抽象状态类,定义一个抽象方法 “写程序”。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 抽象状态 * User: lwx * Date: 2019-04-08 * Time: 21:31 */ public interface WorkState { void writeProgram(Work work); }
上午和中午工作状态类。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 上午工作状态 * User: lwx * Date: 2019-04-08 * Time: 21:32 */ public class ForenoonState implements WorkState { @Override public void writeProgram(Work work) { if (work.getHour() < 12) { System.out.println("当前时间:" + work.getHour() + "点 上午工作,精神百倍。"); } else { //超过12点,则转入中午工作状态 work.setWorkState(new NoonState()); work.writeProgram(); } } }
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 中午工作状态 * User: lwx * Date: 2019-04-08 * Time: 21:39 */ public class NoonState implements WorkState { @Override public void writeProgram(Work work) { if (work.getHour() < 13) { System.out.println("当前时间:" + work.getHour() + "点 饿了,午饭;犯困,午休。"); } else { //超过13点,转入下午工作状态 work.setWorkState(new AfternoonState()); work.writeProgram(); } } }
下午和傍晚工作状态类。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 下午工作状态 * User: lwx * Date: 2019-04-08 * Time: 21:43 */ public class AfternoonState implements WorkState { @Override public void writeProgram(Work work) { if (work.getHour() < 17) { System.out.println("当前时间:" + work.getHour() + "点 下午状态还不错,继续努力。"); } else { work.setWorkState(new EveningState()); work.writeProgram(); } } }
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 晚间工作状态 * User: lwx * Date: 2019-04-08 * Time: 21:45 */ public class EveningState implements WorkState { @Override public void writeProgram(Work work) { if (work.getFinish() == null ? Boolean.FALSE : work.getFinish()) { //完成任务,转入下班状态 work.setWorkState(new RestState()); work.writeProgram(); } else { if (work.getHour() < 21) { System.out.println("当前时间:" + work.getHour() + "点 加班哦,疲劳至极。"); } else { //超过21点则转入睡眠工作状态 work.setWorkState(new SleepingState()); work.writeProgram(); } } } }
睡眠状态和下班休息状态类。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 睡眠状态 * User: lwx * Date: 2019-04-08 * Time: 21:46 */ public class SleepingState implements WorkState { @Override public void writeProgram(Work work) { System.out.println("当前时间:" + work.getHour() + "点 不行了,睡着了。"); } }
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: 下班休息状态 * User: lwx * Date: 2019-04-08 * Time: 21:47 */ public class RestState implements WorkState { @Override public void writeProgram(Work work) { System.out.println("当前时间:" + work.getHour() + "点 下班回家了。"); } }
工作类。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:32 */ public class Work { private WorkState workState; // 钟点 属性,状态转化的依据 private Integer hour; // 任务完成 属性,能下班的依据 private Boolean finish; public Work() { //工作初始化为上午工作状态,即上午9点开始上班 this.workState = new ForenoonState(); } public void writeProgram() { workState.writeProgram(this); } public Boolean getFinish() { return finish; } public void setFinish(Boolean finish) { this.finish = finish; } public Integer getHour() { return hour; } public void setHour(Integer hour) { this.hour = hour; } public WorkState getWorkState() { return workState; } public void setWorkState(WorkState workState) { this.workState = workState; } }
最后是测试类和运行结果。
package com.lwx.state.example; /** * Created with IntelliJ IDEA. * Description: * User: lwx * Date: 2019-04-08 * Time: 21:54 */ public class WorkClient { public static void main(String[] args) { Work work = new Work(); work.setHour(9); work.writeProgram(); work.setHour(10); work.writeProgram(); work.setHour(12); work.writeProgram(); work.setHour(13); work.writeProgram(); work.setHour(14); work.writeProgram(); work.setHour(17); work.writeProgram(); work.setFinish(Boolean.TRUE); work.setHour(19); work.writeProgram(); work.setHour(22); work.writeProgram(); } }
状态模式的优点:
1.将与特定状态相关的行为局部化,并且将不同状态的行为分割化。
2.状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
最后附上demo的githup地址:https://github.com/yijinqincai/design_patterns