一、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ī)--父類定義








狀態(tài)機(jī)--子類實(shí)現(xiàn)
















特點(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ī)管理器


























特點(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)的切換。
-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。