行为类模式(八):状态(State)

定义

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

UML

优点

  1. 把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
  2. 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
  3. 通过把各种状态转移逻辑分不到状态与其子类之间,来减少相互间的依赖。

缺点

  1. 每个具体状态类都会产生一个新类,所以会增加系统需要维护的类的数量。可以使用工厂方法来解决。

应用场景

  1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  2. 一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。

示例

实现一个电梯运行的程序,电梯的几个状态之前可以相互切换,但是状态的改变有前置条件,比如电梯的开门状态下是不能上下跑的。

Java

  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         @Override
101         public void open()
102         {
103             System.out.println("电梯门开启...");
104         }
105 
106         @Override
107         public void run()
108         {
109             System.out.println("电梯门开启时不能上下跑!");
110         }
111 
112         @Override
113         public void stop()
114         {
115             // do nothing;
116         }
117     }
118 
119     /**
120      * 电梯门关闭以后,电梯可以做哪些事情
121      */
122     public static class ClosingState extends LiftState
123     {
124         @Override
125         public void close()
126         {
127             System.out.println("电梯门关闭...");
128         }
129 
130         @Override
131         public void open()
132         {
133             super.context.setLiftState(Context.openningState); // 置为门敞状态
134             super.context.getLiftState().open();
135         }
136 
137         @Override
138         public void run()
139         {
140             super.context.setLiftState(Context.runningState); // 设置为运行状态;
141             super.context.getLiftState().run();
142         }
143 
144         @Override
145         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 LiftState
156     {
157         @Override
158         public void close()
159         {
160             // do nothing
161         }
162 
163         @Override
164         public void open()
165         {
166             // do nothing
167         }
168 
169         @Override
170         public void run()
171         {
172             System.out.println("电梯上下跑...");
173         }
174 
175         @Override
176         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 LiftState
187     {
188         @Override
189         public void close()
190         {
191             // do nothing;
192         }
193 
194         @Override
195         public void open()
196         {
197             super.context.setLiftState(Context.openningState);
198             super.context.getLiftState().open();
199         }
200 
201         @Override
202         public void run()
203         {
204             super.context.setLiftState(Context.runningState);
205             super.context.getLiftState().run();
206         }
207 
208         @Override
209         public void stop()
210         {
211             System.out.println("电梯停止了...");
212         }
213     }
214 }
View Code
原文地址:https://www.cnblogs.com/hammerc/p/4743814.html