state模式
一、State模式定義:
允許一個對象在其狀態改變時,改變它的行為。看起來對象似乎修改了它的類。
二、模式解說
State模式主要解決的是在開發中時常遇到的根據不同的狀態需要進行不同的處理操作的問題,而這樣的問題,大部分人是采用switch-case語句進行處理的,這樣會造成一個問題:分支過多,而且如果加入一個新的狀態就需要對原來的代碼進行編譯。State模式采用了對這些不同的狀態進行封裝的方式處理這類問題,當狀態改變的時候進行處理然后再切換到另一種狀態,也就是說把狀態的切換責任交給了具體的狀態類去負責.同時,State模式和 Strategy模式有很多相似的地方,需要說明的是兩者的思想都是一致的,只不過封裝的東西不同:State模式封裝的是不同的狀態,而Stategy 模式封裝的是不同的算法。
三、結構圖
State模式結構圖如下:
四、怎么使用?
1)定義一個State接口,接口中有一個統一的方法,用以封裝一個特定狀態所對應的行為。
2)定義具體不同狀態類ConcreteSate實現State接口。
3)每一個狀態類都實現環境(Context)一個狀態所對應的行為。
4)定義一個狀態管理器Context.
五、一個例子
1: interface State{
2: public void handle(Context ctx);
3: }
4: class ConcreteStateA implements State{
5:
6: public void handle(Context ctx) {
7: System.out.println("handle by ConcreteStateA");
8: if(ctx!=null){
9: ctx.ChangeState(new ConcreteStateB());
10: }
11:
12: }
13: }
14: class ConcreteStateB implements State{
15:
16: public void handle(Context ctx) {
17: System.out.println("handle by ConcreteStateB");
18: if(ctx!=null){
19: ctx.ChangeState(new ConcreteStateA());
20: }
21:
22: }
23: }
24: class Context{
25: private State _state;
26: public Context(State state){
27: _state=state;
28: }
29: public void request(){
30: if(_state!=null){
31: _state.handle(this);
32: }
33: }
34: public void ChangeState(State s){
35: if(_state!=null){
36: _state=null;
37: }
38: _state=s;
39: }
40: }
41: public class StateClient {
42:
43: public static void main(String[] args) {
44: State state=new ConcreteStateA();
45: Context context=new Context(state);
46: context.request();
47: context.request();
48: context.request();
49: context.request();
50:
51: }
52:
53: }
輸出結果:
handle by ConcreteStateA
handle by ConcreteStateB
handle by ConcreteStateA
handle by ConcreteStateB
每請求一次,狀態就更換一次,就執行對應的行為。
六、適用性
1)一個對象的行為取決于它的狀態,并且它必須在運行時刻根據狀態改變它的行為。
2)一個對象含有龐大的條件分支語句,這些分支依賴于它的狀態。這個狀態通常用一個或多個枚舉常量表示。通常有多個操作包含這一相同的結構。State 模式將每一個分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作為一個對象,這一對象可以不依賴于其他對象而獨立變化。
七、優缺點
1)優點: 避免了為判斷狀態而產生的巨大的if或case語句。 將對象行為交給狀態類維護后,對于上層程序而言,僅需要維護狀態之間的轉換規則。
2)會導致某些系統有過多的具體狀態類。
八、參考
http://www.cppblog.com/converse/archive/2006/08/07/10902.html
http://www.tkk7.com/flying/archive/2006/08/29/66472.html