状态模式
State Pattern:状态模式,是GoF23种设计模式中属于行为型模式的一种。
状态模式是允许通过改变一个对象的内部状态从而改变这个对象的行为,看起来就像是改变了这个对象的实现方式一样。
结构
结合类图分析一下,状态模式一共有三个角色:
- 抽象状态类:这是一个接口(或者抽象类),用于封装与Context的一个特定状态相关的行为。
- 具体状态类:每一个具体的状态实现类都实现一个Context的行为,这些行为和它们的状态是相关的。
- Context类:也被称为上下文环境,这个就是被改变的对象类,里面维护者一个抽象状态类的实例,这个实例用来定义当前这个对象的状态,而我们通过改变这个状态来改变这个实例对象的行为模式。
举例
-
状态模式的使用在生活中也很多,主要就是状态两个字,最为简单的例子就是灯了,灯的状态只有两种一个是开,一个是关,而我们改变了灯的状态之后它就会显示出两种完全不一样的表现形式。
这个例子中灯就是Context上下文环境,而开和关就是两个具体的状态了。
注意
- 状态模式有一个常见的应用是用于替换很多的或者繁杂的if-else语句。
- 状态模式的实现通常是比较负责的,虽然是替换了if-else语句但是如果使用不当,那就会导致程序结构和代码的混乱。
- 其次状态模式的使用必然会增加系统类和对象的个数。
- 需要注意的是状态模式的使用应该是行为受状态约束的时候,而且状态不应该超过五个,多了则会导致状态之间的控制复杂难明。
一个小DEMO
-
场景
嗯,就以灯为例子吧,分为开灯和关灯两个状态。
传统的情况下直接使用if-else就可以实现这个功能
public class LampDemo { public static void main(String[] args) { boolean state = true; for (int i = 0; i < 3; i++) { if (state) { System.out.println("当前的状态为:开"); state = false; }else { System.out.println("当前的状态为:关"); state = true; } } } }
运行结果效果是这样的:
当前的状态为:开 当前的状态为:关 当前的状态为:开
但是现在我们通过状态模式取消掉if-else语句。
-
准备上下文环境,也就是场景中的灯
/** * 状态模式——Context类 * 上下文环境类 也就是场景中的灯啦 * @author wq */ public class Lamp { // 维护一个状态的实例对象 private State state; // getter/setter方法用户读取和更新当前的状态值 public State getState() { return state; } public void setState(State state) { this.state = state; } public Lamp(State state) { this.state = state; } // 显示 public void show() { System.out.print("当前的状态为:"); state.nowState(); state.transform(this); System.out.println("状态已改变,下次生效"); } }
-
抽象状态类
/** * 状态模式——抽象状态类 * @author wq */ public interface State { void transform(Lamp lamp); void nowState(); }
-
具体的状态
/** * 状态模式——具体状态类 * 开 * @author wq */ public class On implements State{ @Override public void transform(Lamp lamp) { lamp.setState(new Off()); } @Override public void nowState() { System.out.println("啪嗒 开了"); } } //------------------------------------------------------------ /** * 状态模式——具体状态类 * 关 * @author wq */ public class Off implements State{ @Override public void transform(Lamp lamp) { lamp.setState(new On()); } @Override public void nowState() { System.out.println("咔嚓 关了"); } }
-
测试类来一个
/** * 状态模式——测试类 * @author wq */ public class Main { public static void main(String[] args) { Lamp lamp = new Lamp(new On()); lamp.show(); lamp.show(); lamp.show(); } }
-
测试走一波
当前的状态为:啪嗒 开了 状态已改变,下次生效 当前的状态为:咔嚓 关了 状态已改变,下次生效 当前的状态为:啪嗒 开了 状态已改变,下次生效
完成!!!