⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statepattern.htm

📁 DesignPattern基于Java方面最好的书
💻 HTM
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>





  
  
  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">





  
  
  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">





  
  
  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">





  
  
  
  
  
  <title>State 模式</title>
</head>


<body>





<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>





<h1><a href="CppGossip.html">Design Pattern:&nbsp;State 模式</a></h1>

如果您不了解TCP的连线方式,在看 <a href="GoF.htm"><span class="wikilink">Gof</span>
的书</a>介绍State模式时,大概会看得一头雾水吧!TCP的连线状态图,光是要了解就要花点精神了,它的连线状态很多,用来说明状态模式确实很适合,但不
适合教导初学模式的人。 <br>
<br>


由简单的开始会比较好理解状态模式的作用,先来看一个例子,如果您有一个只能顺时针转动的瓦斯开关,转动一次的状态为off、
small fire、medium fire与large
fire,您如何在程式中控制状态的变化与行为呢?一个最简单的方式就是用if..else或是switch流程来控制,例如:<br>

<ul>
  <li> State.java
  </li>
</ul>

<pre>public class State { <br>    private int state;<br><br>    public State() { <br>        state = 0; <br>    } <br><br>    public void switchFire() { <br>        if (state == 0) { <br>            state = 1; <br>            System.out.println( "small fire" ); <br>        } else if (state == 1) { <br>            state = 2; <br>            System.out.println( "medium fire" ); <br>        } else if (state == 2) { <br>            state = 3; <br>            System.out.println( "large fire" ); <br>        } else { <br>            state = 0; <br>            System.out.println( "turning off" ); <br>        } <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> Main.java
  </li>
</ul>

<pre>public class Main { <br>     public static void main(String[] args) { <br>        State state = new State();<br><br>        state.switchFire(); <br>        state.switchFire(); <br>        state.switchFire(); <br>        state.switchFire(); <br>    } <br>} <br></pre>

<br>
这个方法很简单,每个人都会,但如果您的状态变化并不是流水式的变化,而是像TCP连线状态一样,会是一个网络图的时候,用
if...else或switch来写的话,您的程式就会乱的不像话了;来考虑如何让物件控制自己的状态转换与所应表现的行为,这个程式可以这
样改写:<br>

<ul>
  <li> IState.java
  </li>
</ul>

<pre>public interface IState { <br>    public void switchFire(FireSwitch sw); <br>} <br></pre>

<br>

<ul>
  <li> OffState
  </li>
</ul>

<pre>public class OffState implements IState { <br>    public void switchFire(FireSwitch sw) { <br>        sw.setState(new SmallState()); <br>        System.out.println( "small fire" ); <br>    } <br>} <br></pre>

<br>

<ul>
  <li> SmallState.java
  </li>
</ul>

<pre>public class SmallState implements IState { <br>    public void switchFire(FireSwitch sw) { <br>        sw.setState(new MediumState()); <br>        System.out.println( "medium fire" ); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> MediumState.java
  </li>
</ul>

<pre>public class MediumState implements IState { <br>    public void switchFire(FireSwitch sw) { <br>        sw.setState(new LargeState()); <br>        System.out.println( "large fire" ); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> LargeState.java
  </li>
</ul>

<pre>public class LargeState implements IState { <br>    public void switchFire(FireSwitch sw) { <br>        sw.setState(new OffState()); <br>        System.out.println( "off fire" ); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> FireSwitch.java
  </li>
</ul>

<pre>public class FireSwitch { <br>    private State current;<br><br>    public FireSwitch() { <br>        current = new OffState(); <br>    }<br><br>    public void setState(State s) { <br>        current = s; <br>    }<br><br>    public void switchFire() { <br>        current.switchFire(this); <br>    }<br>} <br></pre>

<br>

<ul>
  <li> Main.java
  </li>
</ul>

<pre>public class Main { <br>    public static void main(String[] args) { <br>        FireSwitch fireSwitch = new FireSwitch();<br>        fireSwitch.switchFire(); <br>        fireSwitch.switchFire(); <br>        fireSwitch.switchFire(); <br>        fireSwitch.switchFire(); <br>    } <br>} <br></pre>
<br>
程式执行结果与上一个例子是一样的,但这次并没有用流程控制来进行状态转换,而由物件自行控制自己的状态,与必须表现的行为,这个方式就是State 模式,将这个例子的 UML 类别结构画出就如下所示:<br>
<div style="text-align: center;"><img style="width: 454px; height: 211px;" alt="State" title="State" src="images/state-1.jpg"><br>
</div>
<br>

再进一步考虑开关可以顺时针与逆时针转动,这时如果您仍以if...else或switch来写,就会让流程显示复杂,来看看如何使用状态模式来撰
写: <br>

<ul>
  <li> IState.java
  </li>
</ul>

<pre>public interface IState { <br>    public void switchClockWise(FireSwitch sw); <br>    public void switchCountClock(FireSwitch sw); <br>}  <br></pre>

<br>

<ul>
  <li> OffState.java
  </li>
</ul>

<pre>public class OffState implements IState { <br>    public void switchClockWise(FireSwitch sw) { <br>        sw.setState(new SmallState()); <br>        System.out.println("small fire"); <br>    }<br><br>    public void switchCountClock(FireSwitch sw) { <br>        sw.setState(new LargeState()); <br>        System.out.println("large fire"); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> SmallState.java
  </li>
</ul>

<pre>public class SmallState implements IState { <br>    public void switchClockWise(FireSwitch sw) { <br>        sw.setState(new MediumState()); <br>        System.out.println("medium fire"); <br>    } <br><br>    public void switchCountClock(FireSwitch sw) { <br>        sw.setState(new OffState()); <br>        System.out.println("off fire"); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> MediumState.java
  </li>
</ul>

<pre>public class MediumState implements IState { <br>    public void switchClockWise(FireSwitch sw) { <br>        sw.setState(new LargeState()); <br>        System.out.println("large fire"); <br>    }<br> <br>    public void switchCountClock(FireSwitch sw) { <br>        sw.setState(new SmallState()); <br>        System.out.println("small fire"); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> LargeState.java
  </li>
</ul>

<pre>public class LargeState implements State { <br>    public void switchClockWise(FireSwitch sw) { <br>        sw.setState(new OffState()); <br>        System.out.println("off fire"); <br>    }<br><br>    public void switchCountClock(FireSwitch sw) { <br>        sw.setState(new MediumState()); <br>        System.out.println("medium fire"); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> FireSwitch.java
  </li>
</ul>

<pre>public class FireSwitch { <br>    private State current;<br><br>    public FireSwitch() { <br>        current = new OffState(); <br>    }<br><br>    public void setState(State s) { <br>        current = s; <br>    }<br><br>    public void switchClockWise() { <br>        current.switchClockWise(this); <br>    }<br><br>    public void switchCountClock() { <br>       current.switchCountClock(this); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> Main.java
  </li>
</ul>

<pre>public class Main { <br>    public static void main(String[] args) { <br>        FireSwitch fireSwitch = new FireSwitch();<br><br>        fireSwitch.switchClockWise(); <br>        fireSwitch.switchClockWise(); <br>        fireSwitch.switchClockWise(); <br>        fireSwitch.switchClockWise(); <br><br>        System.out.println();<br><br>        fireSwitch.switchCountClock(); <br>        fireSwitch.switchCountClock(); <br>        fireSwitch.switchCountClock(); <br>        fireSwitch.switchCountClock(); <br>    } <br>} <br></pre>

<br>
接下来您可以任意的转动开关了,无论是顺时针转动或是逆时针转动,状态的转换都由物件自己来表现,这是双向状态转换下的例子,
如果一个状态可能转换至三个以上的状态,使用State模式就更可以看出它的好处了,就像Gof的TCP连线例子一样,如果您了解TCP连线,可以看看原
书是如何实现TCP连线之间的状态转换的。 <br>

<br>
State模式的UML结构图如下: <br>
<div style="text-align: center;"><img style="width: 383px; height: 217px;" alt="State" title="State" src="images/state-2.jpg"><br>
</div>
<br>





</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -