設計模式解析和實現(C++, java)之二十--狀態(state)模式

1定義:

 如果一個對象的內在狀態改變時允許改變其行爲,這個對象看起來像是改變了其類。狀態改變和行爲動作分開。每一個狀態對應一個class。

2作用:

State模式主要解決了在開發時需要根據不同的狀態進行不同的處理操作的問題。state模式採用了對這些不同的狀態進行封裝的方式處理這類問題,彈頭狀態改變的時候進行處理然後切換到另一種狀態。也即是狀態的改變交給了具體的狀態類去負責。同時state模式和strategy模式喲很多相似的地方,需要說明的是兩者思想都一致。

 

3UML結構圖:

狀態模式(State)結構圖

 

4使用:

4.1 定義一個state接口,接口使用統一的方法,用以封裝一個特定狀態所對應的行爲。

4.2 定於具體不同狀態類並實現其接口。

4.3 每一個狀態類都實現context一個狀態所對應的行爲。

4.4頂一個狀態管理器context。

 

Java的實現如下:

state類,抽象狀態基類,並定一個接口封裝與context交互的一個特定的行爲。

interface State{
public void handle(Context ctx);
}
class ConcreteStateA implements State{
  
public void handle(Context ctx) {
 System.out.println("handle by ConcreteStateA");
 if(ctx!=null){
 ctx.ChangeState(new ConcreteStateB());
 }
 
}
}
class ConcreteStateB implements State{
  
public void handle(Context ctx) {
 System.out.println("handle by ConcreteStateB");
 if(ctx!=null){
 ctx.ChangeState(new ConcreteStateA());
 }
 
}
}
class Context{
private State _state;
public Context(State state){
 _state=state;
}
public void request(){
 if(_state!=null){
 _state.handle(this);
 }
}
public void ChangeState(State s){
 if(_state!=null){
 _state=null;
 }
 _state=s;
}
}
public class StateClient {
  
public static void main(String[] args) {
 State state=new ConcreteStateA();
 Context context=new Context(state);
 context.request();
 context.request();
 context.request();
 context.request();
  
}
  
}

C++代碼實現:

1)State.h

/* *******************************************************************

#ifndef STATE_H
#define  STATE_H

class  State;

class  Context
{
public :
    Context(State
*  pState);
    
~ Context();
    
void  Request();
    
void  ChangeState(State  * pState);

private :
    State 
* m_pState;
}
;

class  State
{
public :
    
virtual   ~ State() {}

    
virtual   void  Handle(Context *  pContext)  =   0 ;
}
;

class  ConcreateStateA
    : 
public  State
{
public :
    
void  Handle(Context *  pContext);
}
;

class  ConcreateStateB
    : 
public  State
{
public :
    
void  Handle(Context *  pContext);
}
;

#endif


2)State.cpp

/* *******************************************************************


#include 
" State.h "
#include 
< iostream >

Context::Context(State
*  pState)
    : m_pState(pState)
{

}


Context::
~ Context()
{
    delete m_pState;
    m_pState 
=  NULL;
}


void  Context::Request()
{
    
if  (NULL  !=  m_pState)
    
{
        m_pState
-> Handle( this );
    }

}


void  Context::ChangeState(State  * pState)
{
    
if  (NULL  !=  m_pState)
    
{
        delete m_pState;
        m_pState 
=  NULL;
    }

    
    m_pState 
=  pState;
}


void  ConcreateStateA::Handle(Context *  pContext)
{
    std::cout 
<<   " Handle by ConcreateStateA/n " ;
    
    
if  (NULL  !=  pContext)
    
{
        pContext
-> ChangeState( new  ConcreateStateB());
    }

}


void  ConcreateStateB::Handle(Context *  pContext)
{
    std::cout 
<<   " Handle by ConcreateStateB/n " ;

    
if  (NULL  !=  pContext)
    
{
        pContext
-> ChangeState( new  ConcreateStateA());
    }

}


3)Main.cpp
/* *******************************************************************

#include 
" State.h "

int  main()
{
    State 
* pState  =   new  ConcreateStateA();
    Context 
* pContext  =   new  Context(pState);
    pContext
-> Request();
    pContext
-> Request();
    pContext
-> Request();

    delete pContext;

    
return   0 ;
}

  六、適用性

  1)一個對象的行爲取決於它的狀態,並且它必須在運行時刻根據狀態改變它的行爲。

  2)一個對象 含有龐大的條件分支語句,這些分支依賴於它的狀態。這個狀態通常用一個或多個枚舉常量表示。通常有多個操作包含這一相同的結構。State模式將每一個分 支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作爲一個對象,這一對象可以不依賴於其他對象而獨立變化。

  七、優缺點

  1)優點: 避免了爲判斷狀態而產生的巨大的if或case語句。 將對象行爲交給狀態類維護後,對於上層程序而言,僅需要維護狀態之間的轉換規則。

  2)會導致某些系統有過多的具體狀態類。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章