🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 状态模式(State) ## 状态模式的定义与特点 状态(State)模式的定义:对有状态的对象(对象可能会根据不同的情况做出不同的行为),把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。 **优点:** 1. 状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。 2. 减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。 3. 避免if语句有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。 **缺点:** 1. 增加系统的类与对象的个数。 2. 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。 ## **状态模式的结构** 状态模式把受环境改变的对象行为包装在不同的状态对象里,其意图是让一个对象在其内部状态改变的时候,其行为也随之改变。现在我们来分析其基本结构和实现方法。 ## **应用场景:** - 用于对象的不同功能的转换 - 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。 - 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。 ## **模式的结构** 1. 环境(Context)角色:也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。 2. 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。 3. 具体状态(Concrete State)角色:实现抽象状态所对应的行为。 其结构图如图所示 ![](https://img.kancloud.cn/58/a2/58a20e5abd0c583f85b5bcb5b21ca9d7_605x350.png) ``` <pre class="calibre10">``` <span class="token">//环境类</span> class <span class="token4">Context</span> <span class="token3">{</span> private $state<span class="token3">;</span> <span class="token">//定义环境类的初始状态</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteStateA</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//设置新状态</span> public <span class="token5">function</span> <span class="token4">setState</span><span class="token3">(</span>State $state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state <span class="token1">=</span> $state<span class="token3">;</span> <span class="token3">}</span> <span class="token">/** * 读取状态 * @return State */</span> public <span class="token5">function</span> <span class="token4">getState</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token3">;</span> <span class="token3">}</span> <span class="token">//对请求做处理</span> public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//抽象状态类</span> abstract class <span class="token4">State</span> <span class="token3">{</span> abstract public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span>Context $context<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//具体状态A类</span> class <span class="token4">ConcreteStateA</span> extends <span class="token4">State</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span>Context $context<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前状态是 A."</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">ConcreteStateB</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态B类</span> class <span class="token4">ConcreteStateB</span> extends <span class="token4">State</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span>Context $context<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前状态是 B."</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">ConcreteStateA</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">Client</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $context <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Context</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//创建环境</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//处理请求</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> Client<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> 结果: 当前状态是 A<span class="token3">.</span>当前状态是 B<span class="token3">.</span>当前状态是 A<span class="token3">.</span>当前状态是 B<span class="token3">.</span> ``` ``` 不用状态模式时用if判断 ``` <pre class="calibre10">``` <span class="token">//环境类</span> class <span class="token4">Context</span> <span class="token3">{</span> private $state<span class="token3">;</span> <span class="token">//定义环境类的初始状态</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state <span class="token1">=</span> <span class="token6">1</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//设置新状态</span> public <span class="token5">function</span> <span class="token4">setState</span><span class="token3">(</span>int $state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state <span class="token1">=</span> $state<span class="token3">;</span> <span class="token3">}</span> <span class="token">/** * 读取状态 * @return State */</span> public <span class="token5">function</span> <span class="token4">getState</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token3">;</span> <span class="token3">}</span> <span class="token">//对请求做处理</span> public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>state <span class="token1">==</span> <span class="token6">1</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"状态A"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>state <span class="token1">==</span> <span class="token6">2</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"状态B"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> ``` ``` 例子: ``` <pre class="calibre10">``` <span class="token">//环境类</span> class <span class="token4">ScoreContext</span> <span class="token3">{</span> private $state<span class="token3">;</span> <span class="token">//AbstractState</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state <span class="token1">=</span> <span class="token5">new</span> <span class="token4">LowState</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">setState</span><span class="token3">(</span>AbstractState $state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state <span class="token1">=</span> $state<span class="token3">;</span> <span class="token3">}</span> <span class="token">/** * @return AbstractState */</span> public <span class="token5">function</span> <span class="token4">getState</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">add</span><span class="token3">(</span>int $score<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">addScore</span><span class="token3">(</span>$score<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//抽象状态类</span> abstract class <span class="token4">AbstractState</span> <span class="token3">{</span> protected $scoreContext<span class="token3">;</span> <span class="token">//环境 ScoreContext</span> protected $stateName <span class="token1">=</span> <span class="token2">""</span><span class="token3">;</span> <span class="token">//状态名</span> protected $score <span class="token1">=</span> <span class="token6">0</span><span class="token3">;</span> <span class="token">//分数</span> abstract public <span class="token5">function</span> <span class="token4">checkState</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//检查当前状态</span> public <span class="token5">function</span> <span class="token4">addScore</span><span class="token3">(</span>int $x<span class="token3">)</span> <span class="token3">{</span> <span class="token">//设置当前分数</span> $this<span class="token1">-</span><span class="token1">></span>score <span class="token1">+</span><span class="token1">=</span> $x<span class="token3">;</span> echo <span class="token2">"加上:"</span><span class="token3">.</span>$x<span class="token3">.</span><span class="token2">"分,\t当前分数:"</span><span class="token3">.</span>$this<span class="token1">-</span><span class="token1">></span>score<span class="token3">.</span><span class="token2">"分,"</span><span class="token3">;</span> echo $this<span class="token1">-</span><span class="token1">></span>score<span class="token3">;</span> <span class="token">//更具当前分数设置状态</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">checkState</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"\t当前状态:"</span><span class="token3">.</span>$this<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token1">-</span><span class="token1">></span><span class="token4">getState</span><span class="token3">(</span><span class="token3">)</span><span class="token1">-</span><span class="token1">></span>stateName<span class="token3">.</span><span class="token2">"<br>"</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态类:不及格 注意这里的参数是ScoreContext而其他的是AbstractState</span> class <span class="token4">LowState</span> extends <span class="token4">AbstractState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>$h<span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span> <span class="token3">(</span>$h <span class="token5">instanceof</span> <span class="token4">ScoreContext</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext <span class="token1">=</span> $h<span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">=</span> <span class="token2">"不及格"</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>score <span class="token1">=</span> <span class="token6">0</span><span class="token3">;</span> <span class="token3">}</span><span class="token5">else</span> <span class="token5">if</span> <span class="token3">(</span>$h <span class="token5">instanceof</span> <span class="token4">AbstractState</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext <span class="token1">=</span> $h<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">=</span> <span class="token2">"不及格"</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>score <span class="token1">=</span> $h<span class="token1">-</span><span class="token1">></span>score<span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">checkState</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>score <span class="token1">>=</span> <span class="token6">90</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">HighState</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>score <span class="token1">>=</span> <span class="token6">60</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">MiddleState</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态类:中等 </span> class <span class="token4">MiddleState</span> extends <span class="token4">AbstractState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>AbstractState $state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext <span class="token1">=</span> $state<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">=</span> <span class="token2">"中等"</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>score <span class="token1">=</span> $state<span class="token1">-</span><span class="token1">></span>score<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">checkState</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>score <span class="token1"><</span> <span class="token6">60</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">LowState</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>score <span class="token1">>=</span> <span class="token6">90</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">HighState</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态类:优秀</span> class <span class="token4">HighState</span> extends <span class="token4">AbstractState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>AbstractState $state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext <span class="token1">=</span> $state<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">=</span> <span class="token2">"优秀"</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>score <span class="token1">=</span> $state<span class="token1">-</span><span class="token1">></span>score<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">checkState</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>score <span class="token1"><</span> <span class="token6">60</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">LowState</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token5">if</span> <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>score <span class="token1"><</span> <span class="token6">90</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>scoreContext<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">MiddleState</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">ScoreStateTest</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $coreContext <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ScoreContext</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"学生成绩状态测试:<br>"</span><span class="token3">)</span><span class="token3">;</span> $coreContext<span class="token1">-</span><span class="token1">></span><span class="token4">add</span><span class="token3">(</span><span class="token6">30</span><span class="token3">)</span><span class="token3">;</span> $coreContext<span class="token1">-</span><span class="token1">></span><span class="token4">add</span><span class="token3">(</span><span class="token6">40</span><span class="token3">)</span><span class="token3">;</span> $coreContext<span class="token1">-</span><span class="token1">></span><span class="token4">add</span><span class="token3">(</span><span class="token6">25</span><span class="token3">)</span><span class="token3">;</span> $coreContext<span class="token1">-</span><span class="token1">></span><span class="token4">add</span><span class="token3">(</span><span class="token1">-</span><span class="token6">15</span><span class="token3">)</span><span class="token3">;</span> $coreContext<span class="token1">-</span><span class="token1">></span><span class="token4">add</span><span class="token3">(</span><span class="token1">-</span><span class="token6">25</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> ScoreStateTest<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> 结果 学生成绩状态测试: 加上:<span class="token6">30</span>分, 当前分数:<span class="token6">30</span>分<span class="token3">,</span><span class="token6">30</span> 当前状态:不及格 加上:<span class="token6">40</span>分, 当前分数:<span class="token6">70</span>分<span class="token3">,</span><span class="token6">70</span> 当前状态:中等 加上:<span class="token6">25</span>分, 当前分数:<span class="token6">95</span>分<span class="token3">,</span><span class="token6">95</span> 当前状态:优秀 加上:<span class="token1">-</span><span class="token6">15</span>分, 当前分数:<span class="token6">80</span>分<span class="token3">,</span><span class="token6">80</span> 当前状态:中等 加上:<span class="token1">-</span><span class="token6">25</span>分, 当前分数:<span class="token6">55</span>分<span class="token3">,</span><span class="token6">55</span> 当前状态:不及格 ``` ``` 例子2: > 未使用状态模式 ``` <pre class="calibre10">``` abstract class <span class="token4">ILift</span> <span class="token3">{</span> <span class="token">//电梯的四个状态 </span> const OPENING_STATE <span class="token1">=</span> <span class="token6">1</span><span class="token3">;</span> <span class="token">//门敞状态 </span> const CLOSING_STATE <span class="token1">=</span> <span class="token6">2</span><span class="token3">;</span> <span class="token">//门闭状态 </span> const RUNNING_STATE <span class="token1">=</span> <span class="token6">3</span><span class="token3">;</span> <span class="token">//运行状态 </span> const STOPPING_STATE <span class="token1">=</span> <span class="token6">4</span><span class="token3">;</span> <span class="token">//停止状态; </span> <span class="token">//设置电梯的状态 </span> public abstract <span class="token5">function</span> <span class="token4">setState</span><span class="token3">(</span>$state<span class="token3">)</span><span class="token3">;</span> <span class="token">//首先电梯门开启动作 </span> public abstract <span class="token5">function</span> <span class="token4">open</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//电梯门有开启,那当然也就有关闭了 </span> public abstract <span class="token5">function</span> <span class="token4">close</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//电梯要能上能下,跑起来 </span> public abstract <span class="token5">function</span> <span class="token4">run</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//电梯还要能停下来 </span> public abstract <span class="token5">function</span> <span class="token4">stop</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">/** * 电梯的实现类 */</span> class <span class="token4">Lift</span> extends <span class="token4">ILift</span> <span class="token3">{</span> private $state<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">setState</span><span class="token3">(</span>$state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state <span class="token1">=</span> $state<span class="token3">;</span> <span class="token3">}</span> <span class="token">//电梯门关闭 </span> public <span class="token5">function</span> <span class="token4">close</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token">//电梯在什么状态下才能关闭 </span> switch <span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>state<span class="token3">)</span> <span class="token3">{</span> case ILift<span class="token3">:</span><span class="token3">:</span>OPENING_STATE<span class="token3">:</span> <span class="token">//如果是则可以关门,同时修改电梯状态 </span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>CLOSING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>CLOSING_STATE<span class="token3">:</span> <span class="token">//如果电梯就是关门状态,则什么都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>RUNNING_STATE<span class="token3">:</span> <span class="token">//如果是正在运行,门本来就是关闭的,也说明都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>STOPPING_STATE<span class="token3">:</span> <span class="token">//如果是停止状态,本也是关闭的,什么也不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> <span class="token3">}</span> echo <span class="token2">'Lift colse <br>'</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//电梯门开启 </span> public <span class="token5">function</span> <span class="token4">open</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token">//电梯在什么状态才能开启 </span> <span class="token4">switch</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>state<span class="token3">)</span><span class="token3">{</span> case ILift<span class="token3">:</span><span class="token3">:</span>OPENING_STATE<span class="token3">:</span> <span class="token">//如果已经在门敞状态,则什么都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>CLOSING_STATE<span class="token3">:</span> <span class="token">//如是电梯时关闭状态,则可以开启 </span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>OPENING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>RUNNING_STATE<span class="token3">:</span> <span class="token">//正在运行状态,则不能开门,什么都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>STOPPING_STATE<span class="token3">:</span> <span class="token">//停止状态,淡然要开门了 </span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>OPENING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> <span class="token3">}</span> echo <span class="token2">'Lift open <br>'</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//电梯开始跑起来 </span> public <span class="token5">function</span> <span class="token4">run</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token4">switch</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>state<span class="token3">)</span><span class="token3">{</span> case ILift<span class="token3">:</span><span class="token3">:</span>OPENING_STATE<span class="token3">:</span> <span class="token">//如果已经在门敞状态,则不你能运行,什么都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>CLOSING_STATE<span class="token3">:</span> <span class="token">//如是电梯时关闭状态,则可以运行 </span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>RUNNING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>RUNNING_STATE<span class="token3">:</span> <span class="token">//正在运行状态,则什么都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>STOPPING_STATE<span class="token3">:</span> <span class="token">//停止状态,可以运行 </span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>RUNNING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> echo <span class="token2">'Lift run <br>'</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//电梯停止 </span> public <span class="token5">function</span> <span class="token4">stop</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token4">switch</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>state<span class="token3">)</span><span class="token3">{</span> case ILift<span class="token3">:</span><span class="token3">:</span>OPENING_STATE<span class="token3">:</span> <span class="token">//如果已经在门敞状态,那肯定要先停下来的,什么都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>CLOSING_STATE<span class="token3">:</span> <span class="token">//如是电梯时关闭状态,则当然可以停止了 </span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>CLOSING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>RUNNING_STATE<span class="token3">:</span> <span class="token">//正在运行状态,有运行当然那也就有停止了 </span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>CLOSING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> case ILift<span class="token3">:</span><span class="token3">:</span>STOPPING_STATE<span class="token3">:</span> <span class="token">//停止状态,什么都不做 </span> <span class="token">//do nothing; </span> <span class="token5">return</span> <span class="token3">;</span> <span class="token5">break</span><span class="token3">;</span> <span class="token3">}</span> echo <span class="token2">'Lift stop <br>'</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">Client</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">test</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $lift <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Lift</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//电梯的初始条件应该是停止状态 </span> $lift<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>ILift<span class="token3">:</span><span class="token3">:</span>STOPPING_STATE<span class="token3">)</span><span class="token3">;</span> <span class="token">//首先是电梯门开启,人进去 </span> $lift<span class="token1">-</span><span class="token1">></span><span class="token4">open</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//然后电梯门关闭 </span> $lift<span class="token1">-</span><span class="token1">></span><span class="token4">close</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//再然后,电梯跑起来,向上或者向下 </span> $lift<span class="token1">-</span><span class="token1">></span><span class="token4">run</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//最后到达目的地,电梯挺下来 </span> $lift<span class="token1">-</span><span class="token1">></span><span class="token4">stop</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> Client<span class="token3">:</span><span class="token3">:</span><span class="token4">test</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> ``` ``` 【例3】用“状态模式”设计一个多线程的状态转换程序。 分析:多线程存在 5 种状态,分别为新建状态、就绪状态、运行状态、阻塞状态和死亡状态,各个状态当遇到相关方法调用或事件触发时会转换到其他状态 ![](https://img.kancloud.cn/3b/c9/3bc9b23c3c175e27eafafbb01a67995a_609x164.png) 现在先定义一个抽象状态类(TheadState),然后为图 3 所示的每个状态设计一个具体状态类,它们是新建状态(New)、就绪状态(Runnable )、运行状态(Running)、阻塞状态(Blocked)和死亡状态(Dead),每个状态中有触发它们转变状态的方法,环境类(ThreadContext)中先生成一个初始状态(New),并提供相关触发方法 ![](https://img.kancloud.cn/6b/bf/6bbf8dddc11ac2a62adcecf5841f8216_629x670.png) ``` <pre class="calibre10">``` <span class="token">//环境类</span> class <span class="token4">ThreadContext</span> <span class="token3">{</span> private $state<span class="token3">;</span><span class="token">//ThreadState</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">=</span><span class="token5">new</span> <span class="token4">_New</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">setState</span><span class="token3">(</span>ThreadState $state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">=</span>$state<span class="token3">;</span> <span class="token3">}</span> <span class="token">/** * * @return ThreadState */</span> public <span class="token5">function</span> <span class="token4">getState</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token3">;</span> <span class="token3">}</span> <span class="token">//新建状态</span> public <span class="token5">function</span> <span class="token4">start</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">start</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//就绪状态 获取cpu时间</span> public <span class="token5">function</span> <span class="token4">getCPU</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">getCPU</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span><span class="token">//Runnable</span> <span class="token3">}</span> <span class="token">//运行状态 suspend 阻塞</span> public <span class="token5">function</span> <span class="token4">suspend</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">suspend</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span><span class="token">//Running</span> <span class="token3">}</span> <span class="token">//运行状态 结束</span> public <span class="token5">function</span> <span class="token4">stop</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">stop</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span><span class="token">//Running</span> <span class="token3">}</span> <span class="token">//阻塞状态 恢复 </span> public <span class="token5">function</span> <span class="token4">resume</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">resume</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span><span class="token">//Blocked</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//抽象状态类:线程状态</span> abstract class <span class="token4">ThreadState</span> <span class="token3">{</span> protected $stateName<span class="token1">=</span><span class="token2">""</span><span class="token3">;</span> <span class="token">//状态名</span> <span class="token3">}</span> <span class="token">//具体状态类:新建状态</span> class <span class="token4">_New</span> extends <span class="token4">ThreadState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>stateName<span class="token1">=</span><span class="token2">"新建状态"</span><span class="token3">;</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程处于:新建状态."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">start</span><span class="token3">(</span>ThreadContext $hj<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"调用start()方法-->"</span><span class="token3">)</span><span class="token3">;</span> <span class="token5">if</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">===</span> <span class="token2">"新建状态"</span><span class="token3">)</span><span class="token3">{</span> $hj<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">Runnable</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span><span class="token5">else</span><span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程不是新建状态,不能调用start()方法."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态类:就绪状态</span> class <span class="token4">Runnable</span> extends <span class="token4">ThreadState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>stateName<span class="token1">=</span><span class="token2">"就绪状态"</span><span class="token3">;</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程处于:就绪状态."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">getCPU</span><span class="token3">(</span>ThreadContext $hj<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"获得CPU时间-->"</span><span class="token3">)</span><span class="token3">;</span> <span class="token5">if</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>stateName<span class="token1">===</span><span class="token2">"就绪状态"</span><span class="token3">)</span> <span class="token3">{</span> $hj<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">Running</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程不是就绪状态,不能获取CPU."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态类:运行状态</span> class <span class="token4">Running</span> extends <span class="token4">ThreadState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>stateName<span class="token1">=</span><span class="token2">"运行状态"</span><span class="token3">;</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程处于:运行状态."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">suspend</span><span class="token3">(</span>ThreadContext $hj<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"调用suspend()方法-->"</span><span class="token3">)</span><span class="token3">;</span> <span class="token5">if</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">===</span> <span class="token2">"运行状态"</span><span class="token3">)</span> <span class="token3">{</span> $hj<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">Blocked</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程不是运行状态,不能调用suspend()方法."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">stop</span><span class="token3">(</span>ThreadContext $hj<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"调用stop()方法-->"</span><span class="token3">)</span><span class="token3">;</span> <span class="token5">if</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">===</span> <span class="token2">"运行状态"</span><span class="token3">)</span> <span class="token3">{</span> $hj<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">Dead</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程不是运行状态,不能调用stop()方法."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态类:阻塞状态</span> class <span class="token4">Blocked</span> extends <span class="token4">ThreadState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>stateName<span class="token1">=</span><span class="token2">"阻塞状态"</span><span class="token3">;</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程处于:阻塞状态."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">resume</span><span class="token3">(</span>ThreadContext $hj<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"调用resume()方法-->"</span><span class="token3">)</span><span class="token3">;</span> <span class="token5">if</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>stateName <span class="token1">===</span> <span class="token2">"阻塞状态"</span><span class="token3">)</span> <span class="token3">{</span> $hj<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">Runnable</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token5">else</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程不是阻塞状态,不能调用resume()方法."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态类:死亡状态</span> class <span class="token4">Dead</span> extends <span class="token4">ThreadState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>stateName<span class="token1">=</span><span class="token2">"死亡状态"</span><span class="token3">;</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前线程处于:死亡状态."</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">ThreadStateTest</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $context<span class="token1">=</span><span class="token5">new</span> <span class="token4">ThreadContext</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">start</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">getCPU</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">suspend</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">resume</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">getCPU</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">stop</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> ThreadStateTest<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> 结果: 当前线程处于:新建状态<span class="token3">.</span> 调用<span class="token4">start</span><span class="token3">(</span><span class="token3">)</span>方法<span class="token1">--</span><span class="token1">></span>当前线程处于:就绪状态<span class="token3">.</span> 获得CPU时间<span class="token1">--</span><span class="token1">></span>当前线程处于:运行状态<span class="token3">.</span> 调用<span class="token4">suspend</span><span class="token3">(</span><span class="token3">)</span>方法<span class="token1">--</span><span class="token1">></span>当前线程处于:阻塞状态<span class="token3">.</span> 调用<span class="token4">resume</span><span class="token3">(</span><span class="token3">)</span>方法<span class="token1">--</span><span class="token1">></span>当前线程处于:就绪状态<span class="token3">.</span> 获得CPU时间<span class="token1">--</span><span class="token1">></span>当前线程处于:运行状态<span class="token3">.</span> 调用<span class="token4">stop</span><span class="token3">(</span><span class="token3">)</span>方法<span class="token1">--</span><span class="token1">></span>当前线程处于:死亡状态<span class="token3">.</span> ``` ``` ## **状态模式的扩展** 在有些情况下,可能有多个环境对象需要共享一组状态,这时需要引入享元模式,将这些具体状态对象放在集合中供程序共享,其结构图如图所示 ![](https://img.kancloud.cn/04/c6/04c6541d9b75a8b91543c1f8b20d2c10_771x365.png) ``` <pre class="calibre17">``` <span class="token">//环境类</span> class <span class="token4">ShareContext</span> <span class="token3">{</span> private $state<span class="token3">;</span><span class="token">//ShareState</span> private $stateSet<span class="token1">=</span><span class="token4">array</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">=</span><span class="token5">new</span> <span class="token4">ConcreteState1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>stateSet<span class="token3">[</span><span class="token2">"1"</span><span class="token3">]</span><span class="token1">=</span>$this<span class="token1">-</span><span class="token1">></span>state<span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">=</span><span class="token5">new</span> <span class="token4">ConcreteState2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>stateSet<span class="token3">[</span><span class="token2">"2"</span><span class="token3">]</span><span class="token1">=</span>$this<span class="token1">-</span><span class="token1">></span>state<span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">=</span>$this<span class="token1">-</span><span class="token1">></span><span class="token4">getState</span><span class="token3">(</span><span class="token2">"1"</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//设置新状态</span> public <span class="token5">function</span> <span class="token4">setState</span><span class="token3">(</span>ShareState $state<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">=</span>$state<span class="token3">;</span> <span class="token3">}</span> <span class="token">/** * 读取状态 * @param String $key [description] * @return ShareState */</span> public <span class="token5">function</span> <span class="token4">getState</span><span class="token3">(</span>String $key<span class="token3">)</span> <span class="token3">{</span> $s<span class="token1">=</span>$this<span class="token1">-</span><span class="token1">></span>stateSet<span class="token3">[</span>$key<span class="token3">]</span><span class="token3">;</span> <span class="token5">return</span> $s<span class="token3">;</span> <span class="token3">}</span> <span class="token">//对请求做处理</span> public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>state<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//抽象状态类</span> abstract class <span class="token4">ShareState</span> <span class="token3">{</span> public abstract <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span>ShareContext $context<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//具体状态1类</span> class <span class="token4">ConcreteState1</span> extends <span class="token4">ShareState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span>ShareContext $context<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前状态是: 状态1"</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>$context<span class="token1">-</span><span class="token1">></span><span class="token4">getState</span><span class="token3">(</span><span class="token2">"2"</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体状态2类</span> class <span class="token4">ConcreteState2</span> extends <span class="token4">ShareState</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">Handle</span><span class="token3">(</span>ShareContext $context<span class="token3">)</span> <span class="token3">{</span> <span class="token4">print_r</span><span class="token3">(</span><span class="token2">"当前状态是: 状态2"</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">setState</span><span class="token3">(</span>$context<span class="token1">-</span><span class="token1">></span><span class="token4">getState</span><span class="token3">(</span><span class="token2">"1"</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">FlyweightStatePattern</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $context<span class="token1">=</span><span class="token5">new</span> <span class="token4">ShareContext</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//创建环境 </span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//处理请求</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $context<span class="token1">-</span><span class="token1">></span><span class="token4">Handle</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> FlyweightStatePattern<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> ``` ```