posts - 262,  comments - 221,  trackbacks - 0
          注:本文多處引用了WWW.jdon.com網(wǎng)站的《State模式》一文,原文前參見:http://www.jdon.com/designpatterns/designpattern_State.htm

          一、State模式定義:

          不同的狀態(tài),不同的行為;或者說,每個(gè)狀態(tài)有著相應(yīng)的行為.

          二、State模式的適用場合:

          State模式在實(shí)際使用中比較多,適合"狀態(tài)的切換".因?yàn)槲覀兘?jīng)常會(huì)使用If elseif else 進(jìn)行狀態(tài)切換, 如果針對狀態(tài)的這樣判斷切換反復(fù)出現(xiàn),我們就要聯(lián)想到是否可以采取State模式了.

          三、State模式與Command模式的比較:

          前者從調(diào)用者和被調(diào)用者的角度出發(fā),目的是封裝被調(diào)用者的行為,讓調(diào)用者只和統(tǒng)一的頂層接口打交道。后者從對象自身的狀態(tài)出發(fā),不涉及調(diào)用者和被調(diào)用者。是對象自身的狀態(tài)切換導(dǎo)致的行為變化。

          四、“開關(guān)切換狀態(tài)” 和“ 一般的狀態(tài)判斷”區(qū)別:

          “開關(guān)狀態(tài)切換”經(jīng)常發(fā)生在GUI界面的交互過程中,通過結(jié)合對象當(dāng)前狀態(tài)和參數(shù),判斷接下來對象應(yīng)該切換到什么狀態(tài)。被判斷對象和被更新對象都是同一個(gè)。這一點(diǎn)和“一般的狀態(tài)判斷”是不同的,后者是根據(jù)其它對象或?qū)傩缘闹祦砀伦陨淼臓顟B(tài)。被判斷對象和被更新對象不是同一個(gè)。

          例如:if (which==1) state="hello";
             else if (which==2) state="hi";
             else if (which==3) state="bye";

          這是一個(gè) " 一般的狀態(tài)判斷",state值的不同是根據(jù)which變量來決定的,which和state沒有關(guān)系.如果改成:

          if (state.euqals("bye")) state="hello";
          else if (state.euqals("hello")) state="hi";
          else if (state.euqals("hi")) state="bye";

          這就是 "開關(guān)切換狀態(tài)",是將state的狀態(tài)從"hello"切換到"hi",再切換到""bye";再切換到"hello",好象一個(gè)旋轉(zhuǎn)開關(guān),這種狀態(tài)改變就可以使用State模式了.

          五、State模式的構(gòu)成:

          1.state manager 狀態(tài)管理器,就是開關(guān),如上面例子的Context實(shí)際就是一個(gè)state manager, 在state manager中有對狀態(tài)的切換動(dòng)作.

          2.用抽象類或接口實(shí)現(xiàn)的父類,,不同狀態(tài)就是繼承這個(gè)父類的不同子類(也就是不同的狀態(tài)行為)

          六、State模式的例子:

          狀態(tài)機(jī)--父類定義

          public abstract class State// 狀態(tài)行為的父類

                
          // 狀態(tài)機(jī)需要能夠感知上下文的情況,也就是之前的狀態(tài)和目前的情形,所以用Context作為參數(shù)
               public abstract void handlepush(Context c);
            public abstract void handlepull(Context c);
            public abstract void getcolor();

          }

          狀態(tài)機(jī)--子類實(shí)現(xiàn)
          public class BlueState extends State{

            
          public void handlepush(Context c){
               
          //根據(jù)push方法"如果是blue狀態(tài)的切換到green" ;
               c.setState(new GreenState());

            }


            
          public void handlepull(Context c){
                      
          //根據(jù)pull方法"如果是blue狀態(tài)的切換到red" ;
              c.setState(new RedState());
                }


            
          public abstract void getcolor()return (Color.blue)}

          }

          特點(diǎn):

          ·擁有一個(gè)父類,表示各種不同的狀態(tài)。該父類具有三個(gè)典型的方法:
              ·切換到上一個(gè)狀態(tài)
              ·切換到下一個(gè)狀態(tài)
              ·獲取當(dāng)前狀態(tài)
          ·擁有一至多個(gè)子類,在子類中實(shí)現(xiàn)具體的狀態(tài)向前、向后的切換
          ·如果把每個(gè)狀態(tài)看成一個(gè)“狀態(tài)鏈”上的一個(gè)獨(dú)立的節(jié)點(diǎn),那么有N個(gè)狀態(tài),則需要N個(gè)子類。
          ·如果狀態(tài)只支持單向切換,則除了首尾兩個(gè)狀態(tài),其它狀態(tài)的節(jié)點(diǎn)均有兩個(gè)方法,分別是向前/后一個(gè)狀態(tài)的切換
          ·如果狀態(tài)支持雙向切換(例如MP3的自動(dòng)循環(huán)播放功能),則尾節(jié)點(diǎn)可以有兩個(gè)狀態(tài)切換的方法


          狀態(tài)機(jī)管理器
          public class Context{

            
          private Sate state=null; //我們將原來的 Color state 改成了新建的State state;

            
          //setState是用來改變state的狀態(tài) 使用setState實(shí)現(xiàn)狀態(tài)的切換,不同的狀態(tài)傳入不同的State,都是State的子類
            pulic void setState(State state){
              
          this.state=state;
                }


            
          public void push(){
                      
          //狀態(tài)的切換的細(xì)節(jié)部分,在本例中是顏色的變化,已經(jīng)封裝在子類的handlepush中實(shí)現(xiàn),這里無需關(guān)心
              state.handlepush(this);
              
              
          //因?yàn)閟ample要使用state中的一個(gè)切換結(jié)果,使用getColor()
              Sample sample=new Sample(state.getColor());
              sample.operate(); 
                }


            
          public void pull(){
                    state.handlepull(this);

              Sample2 sample2
          =new Sample2(state.getColor());
              sample2.operate(); 

            }


          }

          特點(diǎn):

          ·擁有一個(gè)狀態(tài)機(jī)對象:用于代表當(dāng)前的狀態(tài)
          ·擁有一個(gè)切換到上/下一個(gè)狀態(tài)的方法:實(shí)際上是調(diào)用了狀態(tài)機(jī)自身的切換方法,由于狀態(tài)機(jī)本身已經(jīng)“知道”自己是什么狀態(tài),所以可以方便的切換到上、下一個(gè)狀態(tài)。例如:state.handlePush(this)這個(gè)方法,由于此時(shí)state對象是什么類型已經(jīng)知道(通過對管理器中的狀態(tài)機(jī)賦值),所以切換工作就交給了對象本身了,調(diào)用者不需要知道內(nèi)部是如何切換的。
          ·擁有一個(gè)獲取當(dāng)前狀態(tài)的方法

          我們可以看到,在狀態(tài)機(jī)的上下文中,push和pull方法都把上下文本身作為參數(shù)傳遞給狀態(tài)機(jī),然后在狀態(tài)機(jī)中調(diào)用了上下文的setState(Context c)方法。這是一個(gè)典型的Call-back(回調(diào))機(jī)制。


          七、狀態(tài)機(jī)模式的優(yōu)點(diǎn):

          (1) 封裝轉(zhuǎn)換過程,也就是轉(zhuǎn)換規(guī)則
          (2) 枚舉可能的狀態(tài),因此,需要事先確定狀態(tài)種類。

          使用狀態(tài)模式后,客戶端外界可以直接使用事件Event實(shí)現(xiàn),根本不必關(guān)心該事件導(dǎo)致如何狀態(tài)變化,這些是由狀態(tài)機(jī)等內(nèi)部實(shí)現(xiàn)。這是一種Event-condition-State,狀態(tài)模式封裝了condition-State部分。

          每個(gè)狀態(tài)形成一個(gè)子類,每個(gè)狀態(tài)只關(guān)心它的下一個(gè)可能狀態(tài),從而無形中形成了狀態(tài)轉(zhuǎn)換的規(guī)則。如果新的狀態(tài)加入,只涉及它的前一個(gè)狀態(tài)修改和定義。

          十、狀態(tài)模式和其它模式的結(jié)合應(yīng)用:

          從狀態(tài)模式的實(shí)質(zhì):“只關(guān)心它的下一個(gè)可能狀態(tài)”和客戶端使用特點(diǎn):“使用事件Event實(shí)現(xiàn)”來看,我們可以考慮將觀察者模式(Observer)和狀態(tài)模式(State)結(jié)合起來。被觀察者在改變時(shí)發(fā)送廣播消息(Event事件),觀察著注意并接收該消息后,使用狀態(tài)機(jī)來對當(dāng)前應(yīng)用的上下文進(jìn)行狀態(tài)的切換。



          -------------------------------------------------------------
          生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
          posted on 2008-04-07 18:02 Paul Lin 閱讀(7622) 評(píng)論(2)  編輯  收藏 所屬分類: 模式與重構(gòu)


          FeedBack:
          # re: 設(shè)計(jì)模式總結(jié)-State模式
          2011-11-28 10:45 | joyjjjz
          很好,謝謝!  回復(fù)  更多評(píng)論
            
          # re: 設(shè)計(jì)模式總結(jié)-State模式[未登錄]
          2012-08-28 22:11 | james
          <2012年8月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          常用鏈接

          留言簿(21)

          隨筆分類

          隨筆檔案

          BlogJava熱點(diǎn)博客

          好友博客

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 正镶白旗| 米脂县| 页游| 兰考县| 酒泉市| 九龙城区| 东乡县| 佛冈县| 松桃| 台州市| 辉南县| 孝义市| 五常市| 太原市| 尉犁县| 兴隆县| 宁南县| 抚顺县| 梁山县| 莱州市| 龙口市| 灵丘县| 靖西县| 宣化县| 罗江县| 松原市| 白玉县| 高碑店市| 陕西省| 车险| 通州市| 四会市| 象山县| 濮阳市| 青海省| 金坛市| 高平市| 井研县| 团风县| 琼海市| 兴仁县|