定义
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
UML
优点
- 把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
- 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
- 通过把各种状态转移逻辑分不到状态与其子类之间,来减少相互间的依赖。
缺点
- 每个具体状态类都会产生一个新类,所以会增加系统需要维护的类的数量。可以使用工厂方法来解决。
应用场景
- 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
- 一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。
示例
实现一个电梯运行的程序,电梯的几个状态之前可以相互切换,但是状态的改变有前置条件,比如电梯的开门状态下是不能上下跑的。
Java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 public class Main 2 { 3 public static void main(String[] args) 4 { 5 Context context = new Context(); 6 context.setLiftState(new ClosingState()); 7 context.open(); 8 context.close(); 9 context.run(); 10 context.stop(); 11 12 context.open(); 13 context.run(); 14 } 15 16 public static class Context 17 { 18 // 定义出所有的电梯状态 19 public final static OpenningState openningState = new OpenningState(); 20 public final static ClosingState closingState = new ClosingState(); 21 public final static RunningState runningState = new RunningState(); 22 public final static StoppingState stoppingState = new StoppingState(); 23 24 // 定一个当前电梯状态 25 private LiftState liftState; 26 27 public LiftState getLiftState() 28 { 29 return liftState; 30 } 31 32 public void setLiftState(LiftState liftState) 33 { 34 this.liftState = liftState; 35 // 把当前的环境通知到各个实现类中 36 this.liftState.setContext(this); 37 } 38 39 public void open() 40 { 41 this.liftState.open(); 42 } 43 44 public void close() 45 { 46 this.liftState.close(); 47 } 48 49 public void run() 50 { 51 this.liftState.run(); 52 } 53 54 public void stop() 55 { 56 this.liftState.stop(); 57 } 58 } 59 60 /** 61 * 定义一个电梯的接口 62 */ 63 public static abstract class LiftState 64 { 65 // 定义一个环境角色,也就是封装状态的变换引起的功能变化 66 protected Context context; 67 68 public void setContext(Context _context) 69 { 70 this.context = _context; 71 } 72 73 // 首先电梯门开启动作 74 public abstract void open(); 75 76 // 电梯门有开启,那当然也就有关闭了 77 public abstract void close(); 78 79 // 电梯要能上能下,跑起来 80 public abstract void run(); 81 82 // 电梯还要能停下来,停不下来那就扯淡了 83 public abstract void stop(); 84 } 85 86 /** 87 * 在电梯门开启的状态下能做什么事情 88 */ 89 public static class OpenningState extends LiftState 90 { 91 @Override 92 public void close() 93 { 94 // 状态修改 95 super.context.setLiftState(Context.closingState); 96 // 动作委托为CloseState来执行 97 super.context.getLiftState().close(); 98 } 99 100 @Override101 public void open()102 {103 System.out.println("电梯门开启...");104 }105 106 @Override107 public void run()108 {109 System.out.println("电梯门开启时不能上下跑!");110 }111 112 @Override113 public void stop()114 {115 // do nothing;116 }117 }118 119 /**120 * 电梯门关闭以后,电梯可以做哪些事情121 */122 public static class ClosingState extends LiftState123 {124 @Override125 public void close()126 {127 System.out.println("电梯门关闭...");128 }129 130 @Override131 public void open()132 {133 super.context.setLiftState(Context.openningState); // 置为门敞状态134 super.context.getLiftState().open();135 }136 137 @Override138 public void run()139 {140 super.context.setLiftState(Context.runningState); // 设置为运行状态;141 super.context.getLiftState().run();142 }143 144 @Override145 public void stop()146 {147 super.context.setLiftState(Context.stoppingState); // 设置为停止状态;148 super.context.getLiftState().stop();149 }150 }151 152 /**153 * 电梯在运行状态下能做哪些动作154 */155 public static class RunningState extends LiftState156 {157 @Override158 public void close()159 {160 // do nothing161 }162 163 @Override164 public void open()165 {166 // do nothing167 }168 169 @Override170 public void run()171 {172 System.out.println("电梯上下跑...");173 }174 175 @Override176 public void stop()177 {178 super.context.setLiftState(Context.stoppingState);179 super.context.getLiftState().stop();180 }181 }182 183 /**184 * 在停止状态下能做什么事情185 */186 public static class StoppingState extends LiftState187 {188 @Override189 public void close()190 {191 // do nothing;192 }193 194 @Override195 public void open()196 {197 super.context.setLiftState(Context.openningState);198 super.context.getLiftState().open();199 }200 201 @Override202 public void run()203 {204 super.context.setLiftState(Context.runningState);205 super.context.getLiftState().run();206 }207 208 @Override209 public void stop()210 {211 System.out.println("电梯停止了...");212 }213 }214 }