有限狀態自動機FSM實現(二)--State模式
阿新 • • 發佈:2019-01-24
基於switch結構的有限狀態自動機的實現已經在前一篇博文中給出,請猛擊。
State模式適用於如下情況:
1)一個物件的行為取決於它的狀態,並且必須在執行時根據狀態改變它的行為。
2)一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該物件的狀態。
State模式包含如下物件:
Context物件
1)定義客戶感興趣的介面。
2)維護一個State子類的例項,這個例項定義當前狀態。
State狀態物件
定義一個介面封裝與Context的一個特定狀態相關的行為。
以下圖為例:TCPConnection物件即Context物件, TCPState物件即State狀態物件。
下面是門的有限狀態自動機對應的結構圖:
原始碼如下:
//fsm.h
#pragma once #include <string> using namespace std; enum DoorEvent { EVENT_UNKOWN = 0, EVENT_OPEN_DOOR = 1, EVENT_CLOSE_DOOR = 2, EVENT_LOCK_DOOR = 3, EVENT_UNLOCK_DOOR = 4 }; class Context; class State { public: State(string stateStr="STATE_UNKOWN"):m_stateStr(stateStr){} virtual ~State(){} string getStateStr(){return m_stateStr;} virtual void Handle(Context* pContext, DoorEvent event) = 0; protected: string m_stateStr; }; class StateOpened : public State { public: StateOpened() : State("STATE_OPENED"){} void Handle(Context* pContext, DoorEvent event); }; class StateClosed: public State { public: StateClosed():State("STATE_CLOSED"){} void Handle(Context* pContext, DoorEvent event); }; class StateLocked: public State { public: StateLocked() : State("STATE_LOCKED"){} void Handle(Context* pContext, DoorEvent event); }; class StateUnlocked: public State { public: StateUnlocked() : State("STATE_UNLOCKED"){} void Handle(Context* pContext, DoorEvent event); }; class Context { public: Context(State* pState){m_state = pState;} ~Context(){} void Request(DoorEvent event){m_state->Handle(this, event);} void ChangeState(State *pState){m_state = pState;} string getStateStr(void){return m_state->getStateStr();} private: State *m_state; };
//fsm.cpp
#include <iostream> #include <iomanip> using namespace std; #include "fsm.h" #include <Windows.h> const char *DoorEventStr[] = { "EVENT_UNKOWN", "EVENT_OPEN_DOOR", "EVENT_CLOSE_DOOR", "EVENT_LOCK_DOOR", "EVENT_UNLOCK_DOOR" }; void StateOpened::Handle(Context* pContext, DoorEvent event) { switch(event) { case EVENT_CLOSE_DOOR: pContext->ChangeState(new StateClosed); break; default: break; } } void StateClosed::Handle(Context* pContext, DoorEvent event) { switch(event) { case EVENT_LOCK_DOOR: pContext->ChangeState(new StateLocked); break; case EVENT_OPEN_DOOR: pContext->ChangeState(new StateOpened); break; default: break; } } void StateLocked::Handle(Context* pContext, DoorEvent event) { switch(event) { case EVENT_UNLOCK_DOOR: pContext->ChangeState(new StateUnlocked); break; default: break; } } void StateUnlocked::Handle(Context* pContext, DoorEvent event) { switch(event) { case EVENT_OPEN_DOOR: pContext->ChangeState(new StateOpened); break; case EVENT_LOCK_DOOR: pContext->ChangeState(new StateLocked); break; default: break; } } int main(int argc, char* argv[]) { DoorEvent event = EVENT_UNKOWN; Context *pContext = new Context(new StateOpened); int index = 0; while(index < 10) { switch(index%4+1) { case 1: event = EVENT_OPEN_DOOR; break; case 2: event = EVENT_CLOSE_DOOR; break; case 3: event = EVENT_LOCK_DOOR; break; case 4: event = EVENT_UNLOCK_DOOR; break; default: break; } index++; string lastStat = pContext->getStateStr(); pContext->Request(event); cout<<setiosflags(ios::left) <<setw(15)<<lastStat <<" - " <<setw(20)<<DoorEventStr[event] <<" - " <<setw(15)<<pContext->getStateStr()<<endl; Sleep(1); } return 0; }
參考文獻:
《設計模式——可複用面向物件軟體的基礎》
http://blog.csdn.net/uyghfjhh/article/details/19651225
http://blog.csdn.net/xiexievv/article/details/6733470