細心!用心!耐心!

          吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學業,五六點粗墨,七八筆買賣,九十道人情。

          BlogJava 聯系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks
          如果您不瞭解TCP的連線方式,在看 Gof 的書介紹State模式時,大概會看得一頭霧水吧!TCP的連線狀態圖,光是要瞭解就要花點精神了,它的連線狀態很多,用來說明狀態模式確實很適合,但不適合教導初學模式的人。

          由簡單的開始會比較好理解狀態模式的作用,先來看一個例子,如果您有一個只能順時針轉動的瓦斯開關,轉動一次的狀態為off、 small fire、medium fire與large fire,您如何在程式中控制狀態的變化與行為呢?一個最簡單的方式就是用if..else或是switch流程來控制,例如:
          • State.java
          public class State { 
          private int state;

          public State() {
          state = 0;
          }

          public void switchFire() {
          if (state == 0) {
          state = 1;
          System.out.println( "small fire" );
          } else if (state == 1) {
          state = 2;
          System.out.println( "medium fire" );
          } else if (state == 2) {
          state = 3;
          System.out.println( "large fire" );
          } else {
          state = 0;
          System.out.println( "turning off" );
          }
          }
          }

          • Main.java
          public class Main { 
          public static void main(String[] args) {
          State state = new State();

          state.switchFire();
          state.switchFire();
          state.switchFire();
          state.switchFire();
          }
          }

          這個方法很簡單,每個人都會,但如果您的狀態變化並不是流水式的變化,而是像TCP連線狀態一樣,會是一個網絡圖的時候,用 if...else或switch來寫的話,您的程式就會亂的不像話了;來考慮如何讓物件控制自己的狀態轉換與所應表現的行為,這個程式可以這樣改寫:
          • IState.java
          public interface IState { 
          public void switchFire(FireSwitch sw);
          }

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

          • SmallState.java
          public class SmallState implements IState { 
          public void switchFire(FireSwitch sw) {
          sw.setState(new MediumState());
          System.out.println( "medium fire" );
          }
          }

          • MediumState.java
          public class MediumState implements IState { 
          public void switchFire(FireSwitch sw) {
          sw.setState(new LargeState());
          System.out.println( "large fire" );
          }
          }

          • LargeState.java
          public class LargeState implements IState { 
          public void switchFire(FireSwitch sw) {
          sw.setState(new OffState());
          System.out.println( "off fire" );
          }
          }

          • FireSwitch.java
          public class FireSwitch { 
          private State current;

          public FireSwitch() {
          current = new OffState();
          }

          public void setState(State s) {
          current = s;
          }

          public void switchFire() {
          current.switchFire(this);
          }
          }

          • Main.java
          public class Main { 
          public static void main(String[] args) {
          FireSwitch fireSwitch = new FireSwitch();
          fireSwitch.switchFire();
          fireSwitch.switchFire();
          fireSwitch.switchFire();
          fireSwitch.switchFire();
          }
          }

          程式執行結果與上一個例子是一樣的,但這次並沒有用流程控制來進行狀態轉換,而由物件自行控制自己的狀態,與必須表現的行為,這個方式就是State 模式,將這個例子的 UML 類別結構畫出就如下所示:
          State

          再進一步考慮開關可以順時針與逆時針轉動,這時如果您仍以if...else或switch來寫,就會讓流程顯示複雜,來看看如何使用狀態模式來撰寫:
          • IState.java
          public interface IState { 
          public void switchClockWise(FireSwitch sw);
          public void switchCountClock(FireSwitch sw);
          }

          • OffState.java
          public class OffState implements IState { 
          public void switchClockWise(FireSwitch sw) {
          sw.setState(new SmallState());
          System.out.println("small fire");
          }

          public void switchCountClock(FireSwitch sw) {
          sw.setState(new LargeState());
          System.out.println("large fire");
          }
          }

          • SmallState.java
          public class SmallState implements IState { 
          public void switchClockWise(FireSwitch sw) {
          sw.setState(new MediumState());
          System.out.println("medium fire");
          }

          public void switchCountClock(FireSwitch sw) {
          sw.setState(new OffState());
          System.out.println("off fire");
          }
          }

          • MediumState.java
          public class MediumState implements IState { 
          public void switchClockWise(FireSwitch sw) {
          sw.setState(new LargeState());
          System.out.println("large fire");
          }

          public void switchCountClock(FireSwitch sw) {
          sw.setState(new SmallState());
          System.out.println("small fire");
          }
          }

          • LargeState.java
          public class LargeState implements State { 
          public void switchClockWise(FireSwitch sw) {
          sw.setState(new OffState());
          System.out.println("off fire");
          }

          public void switchCountClock(FireSwitch sw) {
          sw.setState(new MediumState());
          System.out.println("medium fire");
          }
          }

          • FireSwitch.java
          public class FireSwitch { 
          private State current;

          public FireSwitch() {
          current = new OffState();
          }

          public void setState(State s) {
          current = s;
          }

          public void switchClockWise() {
          current.switchClockWise(this);
          }

          public void switchCountClock() {
          current.switchCountClock(this);
          }
          }

          • Main.java
          public class Main { 
          public static void main(String[] args) {
          FireSwitch fireSwitch = new FireSwitch();

          fireSwitch.switchClockWise();
          fireSwitch.switchClockWise();
          fireSwitch.switchClockWise();
          fireSwitch.switchClockWise();

          System.out.println();

          fireSwitch.switchCountClock();
          fireSwitch.switchCountClock();
          fireSwitch.switchCountClock();
          fireSwitch.switchCountClock();
          }
          }

          接下來您可以任意的轉動開關了,無論是順時針轉動或是逆時針轉動,狀態的轉換都由物件自己來表現,這是雙向狀態轉換下的例子,如果一個狀態可能轉換至三個以上的狀態,使用State模式就更可以看出它的好處了,就像Gof的TCP連線例子一樣,如果您瞭解TCP連線,可以看看原書是如何實現TCP連線之間的狀態轉換的。

          State模式的UML結構圖如下:
          State
          posted on 2007-04-17 10:50 張金鵬 閱讀(227) 評論(0)  編輯  收藏 所屬分類: Behavioral 模式
          主站蜘蛛池模板: 大埔县| 山阴县| 防城港市| 黄龙县| 晋江市| 云阳县| 南部县| 新龙县| 新蔡县| 峨眉山市| 延津县| 东辽县| 宁海县| SHOW| 江孜县| 溧水县| 岗巴县| 黑山县| 百色市| 安吉县| 天等县| 根河市| 商洛市| 黑山县| 固镇县| 大关县| 维西| 沈丘县| 双峰县| 湟中县| 喀喇沁旗| 台山市| 江门市| 平塘县| 错那县| 长垣县| 延吉市| 襄汾县| 吴旗县| 商丘市| 顺平县|