samtiger


          QQ:418148757
          Name:yangchuan
          數(shù)據(jù)加載中……
          設(shè)計(jì)模式之狀態(tài)模式

                  哎,最近一直在河北華為移動(dòng)項(xiàng)目組做外包,一直也沒有機(jī)會(huì)寫什么代碼,也沒機(jī)會(huì)上網(wǎng) ,真的是郁悶死了。
                 
                 我們?cè)谧瞿骋恍┎僮鞯臅r(shí)候,遇到不同狀態(tài)的時(shí)候就會(huì)有不同的處理方式。為了判別這些狀態(tài),我們必然會(huì)使用大量的if else語句來做狀態(tài)判斷處理。而隨著if else(或switch case)語句的增多,程序的可讀性,擴(kuò)展性也會(huì)變得很弱。維護(hù)也會(huì)很麻煩,你可能看到過有的代碼中 一個(gè)函數(shù)就有n多if語句,代碼甚至超過了上千行。
                  舉一個(gè)例子:我們給一部手機(jī)打電話,就可能出現(xiàn)這幾種情況:用戶開機(jī),用戶關(guān)機(jī),用戶欠費(fèi)停機(jī),用戶消戶等。 所以當(dāng)我們撥打這個(gè)號(hào)碼的時(shí)候:系統(tǒng)就要判斷,該用戶是否在開機(jī)且不忙狀態(tài),又或者是關(guān)機(jī),欠費(fèi)等狀態(tài)。但不管是那種狀態(tài)我們都應(yīng)給出對(duì)應(yīng)的處理操作。下面我們用代碼來模擬一下這個(gè)過程。

           1/***********************************************************************
           2 * Module:  Context.java
           3 * Author:  yang00013
           4 * Purpose: Defines the Class Context
           5 ***********************************************************************/

           6
           7import java.util.*;
           8
           9
          10public class MobileTelephone{
          11   //開機(jī)且用戶沒使用的狀態(tài)
          12   private int waitState = 1;
          13   //關(guān)機(jī)狀態(tài)
          14   private int closeState = 2;
          15   //停機(jī)狀態(tài)
          16   private int stopState = 3;
          17  // 已消戶
          18   private int logoutState = 4;
          19  // 撥通
          20  private int connectState = 5;
          21   //當(dāng)前狀態(tài)
          22   private int state = openState;   
          23   
          24  
          25   //打電話操作
          26   public void call() {
          27     if (state == waitState )
          28     {
          29        system.out.println("連接成功,可以通話");
          30        //改變狀態(tài)為連接通話狀態(tài)
          31        changeState(connectState);            
          32     }
          else if(state == closeState )
          33       {
          34            system.out.println("用戶已關(guān)機(jī)");
          35       }
          else if(state == stopState){
          36            system.out.println("用戶欠費(fèi)停機(jī)");
          37       }
          else if (state == connectState){
          38            system.out.println("用戶正在通話,請(qǐng)稍后再撥!"); 
          39     }

          40
          41   }
             
          42   
          43   //通話計(jì)時(shí)
          44   public void countTime(){
          45     if (state == connectState )
          46     {
          47        system.out.println("計(jì)時(shí)處理。。。");
          48        system.out.println("通話結(jié)束,計(jì)時(shí)結(jié)束");
          49        changeState(waitState);            
          50     }
          else if(state = waitState){
          51        system.out.println("電話不在連接狀態(tài),不計(jì)時(shí)。。。");
          52     }
          else if(state == closeState )
          53       {
          54            system.out.println("用戶已關(guān)機(jī)");
          55       }
          else if(state == stopState){
          56            system.out.println("用戶欠費(fèi)停機(jī)");
          57       }

          58
          59  }

          60  
          61    //其他操作:比如開機(jī),關(guān)機(jī),欠費(fèi)開機(jī)等操作與上雷同,在此省略。。。
          62 
          63
          64   public void changeState(int concreteState) {
          65      this.state = concreteState;
          66   }

          67
          68}

                   注意,看看上面的代碼,顯然它已經(jīng)完成了我們的基本業(yè)務(wù)操作,但是,一旦我們有新的狀態(tài)加入的話,我們勢(shì)必要在每個(gè)業(yè)務(wù)方法里邊增加相應(yīng)的else if語句。所以加入x個(gè)狀態(tài)就有可能加入n*x條else if語句,n表示函數(shù)(業(yè)務(wù)方法)的數(shù)量。

          狀態(tài)模式:把不同狀態(tài)的操作分散到不同的狀態(tài)對(duì)象里去完成。看看狀態(tài)類的uml類圖。
              

                 從上圖可以看出,每一個(gè)狀態(tài)類都會(huì)去處理所有的業(yè)務(wù)方法,根據(jù)他自身的狀態(tài),去讓不同函數(shù)(業(yè)務(wù)方法)作相應(yīng)的不同處理。而我們先前的方式是,在不同的函數(shù)(業(yè)務(wù)方法)里去判斷不同狀態(tài),然后分別對(duì)每一個(gè)狀態(tài)作不同的處理。很顯然,我們采用狀態(tài)模式的方式在后續(xù)擴(kuò)張和維護(hù)能力上都得到了很大程度提高,比如我們先加入一個(gè)狀態(tài),我就只僅僅需要加入一個(gè)相應(yīng)的狀態(tài)類就可以了。代碼量也就是實(shí)現(xiàn)該狀態(tài)下各個(gè)函數(shù)的不同處理過程而已。好,看看實(shí)現(xiàn)代碼:

           1/***********************************************************************
           2 * Module:  IState.java
           3 * Author:  yang00013
           4 * Purpose: Defines the Interface IState
           5 ***********************************************************************/

           6
           7import java.util.*;
           8
           9
          10public interface IState {
          11   
          12   void call();
          13   
          14   void countTimes();
          15   
          16  // 其他操作。
          17
          18}
           空閑狀態(tài):
           1/***********************************************************************
           2 * Module:  ConcreteStateA.java
           3 * Author:  yang00013
           4 * Purpose: Defines the Class ConcreteStateA
           5 ***********************************************************************/

           6
           7import java.util.*;
           8
           9
          10public class WaitState implements IState {
          11   
          12   private Context context;   
          13   
          14   public void call() {
          15       //做連接操作
          16        system.out.println("連接成功,可以通話");
          17        //改變狀態(tài)為連接通話狀態(tài)
          18        context。changeState(context.getConnectState());         
          19   }

          20   
          21   
          22   public void countTimes() {
          23       system.out.print("電話不在連接狀態(tài),不能計(jì)時(shí)");
          24   }

          25   
          26   
          27  
          28
          29}
          通話狀態(tài):
           1/***********************************************************************
           2 * Module:  ConcreteStateB.java
           3 * Author:  yang00013
           4 * Purpose: Defines the Class ConcreteStateB
           5 ***********************************************************************/

           6
           7import java.util.*;
           8
           9
          10public class ConnectState implements IState {
          11
          12   private Context context;
          13   
          14   
          15   public void call() {
          16      system.out.print("用戶正在通話,請(qǐng)稍后再撥");
          17   }

          18   
          19
          20   public void countTimes() {
          21      system.out.println("計(jì)時(shí)處理。。。");
          22      system.out.println("通話結(jié)束,計(jì)時(shí)結(jié)束");
          23      context.changeState(context.getWaitState());    
          24   }

          25   
          26  
          27   
          28}
          新的手機(jī)類
           1/***********************************************************************
           2 * Module:  Context.java
           3 * Author:  yang00013
           4 * Purpose: Defines the Class Context
           5 ***********************************************************************/

           6
           7import java.util.*;
           8
           9
          10public class MobileTelephone {
          11   //開機(jī)且空閑狀態(tài)
          12   private State waitState = new waitState();
          13   //通話連接狀態(tài)
          14   private State connectState = new ConnectState();
          15   //關(guān)機(jī)狀態(tài)
          16   private State stopState = new stopState();
          17  //其它狀態(tài)與上了雷同,在此省略。。。
          18   //當(dāng)前狀態(tài)
          19   private State state = waitState;   
          20   
          21   //撥打操作
          22   public void call() {
          23      state.call(); 
          24   }
             
          25  //計(jì)時(shí)操作
          26   public void countTimes() {
          27     state.countTimes();
          28   }
             
          29  
          30  
          31   
          32   public void chageState(State concreteState) {
          33      this.state = concreteState;
          34   }

          35
          36
          37   //setter/getter 方法列表
          38   
          39}
                 狀態(tài)模式和策略模式的最大區(qū)別在于它有狀態(tài)間的切換,一個(gè)狀態(tài)完了,就要切換到它下一個(gè)狀態(tài)。

          posted on 2008-03-14 13:51 sam.chuan.yang 閱讀(5904) 評(píng)論(2)  編輯  收藏 所屬分類: 23設(shè)計(jì)模式的理解

          評(píng)論

          # re: 設(shè)計(jì)模式之狀態(tài)模式[未登錄] 2010-01-26 09:37 Yang

          首先感謝博主的描述,我覺得是網(wǎng)上比較好的對(duì)狀態(tài)模式的闡述,不過那個(gè)UML圖的菱形顏色貌似錯(cuò)了,使用的是組合,顏色應(yīng)該是白色吧?黑色是聚合,生命周期不同。不過圖畫的很好。

          # re: 設(shè)計(jì)模式之狀態(tài)模式 2010-01-26 18:33 sam.chuan.yang

          例子用的是組合,圖也沒有錯(cuò),當(dāng)然這種對(duì)狀態(tài)類的依耐性比較強(qiáng),其實(shí)可以用聚合關(guān)系,比如用依賴注入的方式將實(shí)際狀態(tài)對(duì)象注入進(jìn)來,而不是自己new一個(gè),感謝你的關(guān)注,不當(dāng)之處,請(qǐng)多多多交流。謝謝

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 新晃| 廊坊市| 宜宾县| 通河县| 额尔古纳市| 皋兰县| 资源县| 万荣县| 江阴市| 长岛县| 济宁市| 雅安市| 长阳| 固镇县| 项城市| 闽清县| 额尔古纳市| 资阳市| 崇左市| 德阳市| 井冈山市| 磐石市| 西青区| 广南县| 鄱阳县| 山西省| 图片| 珠海市| 赤峰市| 余庆县| 泗水县| 永登县| 南皮县| 措美县| 文水县| 临安市| 福安市| 宾阳县| 宣汉县| 扶风县| 德江县|