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模式的適用場(chǎng)合:

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

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

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

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

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

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

          這是一個(gè) " 一般的狀態(tài)判斷",state值的不同是根據(jù)which變量來(lái)決定的,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中有對(duì)狀態(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; //我們將原來(lái)的 Color state 改成了新建的State state;

            
          //setState是用來(lái)改變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),這里無(wú)需關(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ī)對(duì)象:用于代表當(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對(duì)象是什么類型已經(jīng)知道(通過對(duì)管理器中的狀態(tài)機(jī)賦值),所以切換工作就交給了對(duì)象本身了,調(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),從而無(wú)形中形成了狀態(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)”來(lái)看,我們可以考慮將觀察者模式(Observer)和狀態(tài)模式(State)結(jié)合起來(lái)。被觀察者在改變時(shí)發(fā)送廣播消息(Event事件),觀察著注意并接收該消息后,使用狀態(tài)機(jī)來(lái)對(duì)當(dāng)前應(yīng)用的上下文進(jìn)行狀態(tài)的切換。



          -------------------------------------------------------------
          生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
          posted on 2008-04-07 18:02 Paul Lin 閱讀(7621) 評(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
          <2008年4月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          常用鏈接

          留言簿(21)

          隨筆分類

          隨筆檔案

          BlogJava熱點(diǎn)博客

          好友博客

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 安丘市| 修武县| 长乐市| 大悟县| 盐源县| 隆安县| 托克托县| 洞头县| 永平县| 翁牛特旗| 清流县| 通许县| 汝州市| 铜陵市| 沛县| 孟连| 盐源县| 镇平县| 陆丰市| 奉新县| 新营市| 秦安县| 炎陵县| 双辽市| 乌苏市| 光山县| 普兰店市| 宾川县| 含山县| 东城区| 临沧市| 甘孜| 定陶县| 台南市| 东辽县| 来安县| 大余县| 永泰县| 汪清县| 临西县| 丽水市|