"围观"设计模式(21)-举动型之状态模式(State Pattern)
状态模式--允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。----百度百科
个人理解
状态模式应该说可以理解为某种状态下,程序的执行流程可能会发生变化,类似于交通灯,红灯的时候停下,绿灯行走,黄灯时等一等,这就是三种状态下我们人对其作出的相应的变化。再比如,公交车应该都坐过的,公交车停车的时候,可以上车和下车;公交车行驶的时候,不允许下车和上车,那么,这里公交车停车和行驶是两种状态,这两种状态对于后续人上车下车的行为产生了一定的影响。通俗点就是说,某种状态作为先决条件时,后面的行为受到了前面的这种状态的影响,这种情况比较适合运用状态模式。
案例解析
通用的模板
下面来看一个比较通用的模板
public class Context { // 定义状态 public final static State STATE1 = new ConcreteState1(); public final static State STATE2 = new ConcreteState2(); // 当前状态 private State currentState; public State getCurrentState() { return currentState; } // 设置当前状态 public void setCurrentState(State currentState) { this.currentState = currentState; currentState.setContext(this); } // 行为委托 public void behave1(){ this.currentState.behave1(); } public void behave2(){ this.currentState.behave2(); } }Context类:环境角色,定义客户端需要的接口,并且负责具体的状态的切换。
State类为抽象状态角色,定义对象的状态,并且封装环境角色以实现状态的切换。
public abstract class State { // 定义一个环境角色,提供子类访问 protected Context context; // 设置环境角色 public void setContext(Context context){ this.context = context; } // 行为1 public abstract void behave1(); // 行为2 public abstract void behave2(); }
抽象类的具体实现类,需要完成本状态的行为以及要切换到的状态的行为管理,也就是,本状态要做的事做完,然后跳转其要切换的状态。
public class ConcreteState1 extends State { @Override public void behave1() { System.out.println("状态1"); } @Override public void behave2() { super.context.setCurrentState(Context.STATE2); super.context.behave2(); } }
红绿灯案例与状态模式
在具体的实现时与之前的部分有所不同,或许是案例的原因,基本的功能和原理是相符的。
State--抽象状态角色,定义好三个不同的交通灯的情况下,对应的动作。
public abstract class State { // 设置环境角色 protected Context context; public void setContext(Context context) { this.context = context; } public abstract void pass(); public abstract void stop(); public abstract void waiting(); }
Context环境角色,定义调用者需要的接口,负责具体的状态的切换。
public class Context { public final static State REDLIGHT = new RedLight(); public final static State GREENLIGHT = new GreenLight(); public final static State YELLOWLIGHT = new YellowLight(); // 当前状态 private State currentState; public State getCurrentState() { return currentState; } public void setCurrentState(State currentState) { this.currentState = currentState; this.currentState.setContext(this); } public void pass() { this.currentState.pass(); } public void stop() { this.currentState.stop(); } public void waiting() { this.currentState.waiting(); } }
状态的具体实现类,完成本状态应有的行为,并且切换到相应的状态去。
public class RedLight extends State { @Override public void pass() { // 不允许通过 } @Override public void stop() { System.out.println("红灯停止"); try { waiting(); new Thread().sleep(1000); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } super.context.setCurrentState(Context.GREENLIGHT); super.context.pass(); } @Override public void waiting() { System.out.println("等待1s钟"); } }
测试类
public class WY { public static void main(String[] args) { Context context = new Context(); // 红灯 context.setCurrentState(new RedLight()); context.stop(); System.out.println("=================="); // 绿灯 context.setCurrentState(new GreenLight()); context.pass(); System.out.println("=================="); // 黄灯 context.setCurrentState(new YellowLight()); context.waiting(); } }
状态模式优点
1. 结构清晰(和if..else以及switch相比)。
2. 遵循了开闭原则和单一职责原则。
3. 封装性好,状态的变化放在类的内部,外部不需要知道类内部如何实现状态和行为的变化。
状态模式的缺点
子类太多的话导致类膨胀,不便于管理和维护,在设计时需要考虑到这一点。
状态模式适用场景
1. 存在多种状态,行为受到状态的影响。
2. 条件、判断替代者
代码下载
设计模式实例源代码下载
推荐阅读
"围观"设计模式(16)--结构型之组合模式(Composite Pattern)
"围观"设计模式(17)--结构型之享元模式(Flyweight Pattern)
"围观"设计模式(18)--行为型之模板方法模式(TemplateMethod Pattern)
"围观"设计模式(19)--行为型之观察者模式(Observer Pattern)
"围观"设计模式(20)--行为型之策略模式(Strategy Pattern)