1. 狀態
物件在其生命週期內,所處於的運動和發展階段。例如:人可以處於工作中這個狀態,也可以處於娛樂中狀態。
狀態應該有上下文環境。例如:人處於工作中狀態,要屬於職業生涯狀態而不能是退休狀態,也必須是活著的,而不能是死亡的狀態。狀態可以有子狀態。例如:工作中狀態,可以有開會中,會客中,被訓斥中等子狀態。
2. 狀態機
由許多相關狀態構成的集合。把乙個物件,或者乙個系統看做是乙個狀態機。
struct m : state_machine< m, a > {}; //這裡定義了乙個狀態機類m。初始狀態在a
struct a : ******_state{}; //這裡定義乙個了狀態a,屬於m狀態機。
struct a : ******_state{}; //這裡定義乙個了狀態a,屬於m狀態機。a狀態有初始子狀態a1
其實可以狀態機看做狀態,把狀態看做狀態機,區別不是很大。
如果不考慮「歷史狀態」,當進入狀態m後,會自動進入初始狀態a,然後自動進入a1。如果a1有子狀態a11,就會進入a11。
3. 狀態本地儲存
一般的,狀態物件裡不存放任何變數。我們把資料存放到狀態機m裡。這樣做不方便。例如:我們工作相關的資料和娛樂相關的資料都放到「生存」這個狀態機類裡,首先就失去了資料封裝隱藏的好處了。其次,每個狀態或子狀態只要能訪問到狀態機,就可讀寫任意其他狀態需要的重要資訊,容易導致類似「全域性變數」帶來的壞處。
利用context<>, state_cast<>等機制,我們可以容易的訪問當前狀態的「容器狀態」和「啟用的子狀態」的引用,然後呼叫set,get方法去改變他們的資料值。
4.事件
狀態機對外部或內部事件感興趣,引起狀態轉移。例如:當人處於混混欲睡狀態時,突然收到乙個好訊息事件,人就改變為興奮狀態了。
struct evt: sc::event< evt > {}; //事件類。當然可以加入自己想傳達的任何資訊。
struct evt: sc::event< evt > ; //可以加一些成員變數進去。
5. 狀態轉移
當狀態感覺到乙個事件發生時,可以對這個事件做出反應。狀態轉移就是一條「規則」,指明如何反應。例如:
當有人罵你這個事件發生時,你可以根據「惡意度」,罵人者與你的「親密程度」,選擇忽略這個事件,或者轉移到「暴怒狀態」,或者做出一定回擊。
struct a1 : ******_state; //狀態轉移規則用typedef說明,注意reactions不能拼錯。
typedef transition< evt, b > reactions; //當遇到事件evt是,就轉移到狀態b。
狀態轉移能從乙個狀態跳轉到任意的乙個狀態,即使狀態是巢狀的深層子狀態。
d->c->b->a
innermostcommonouter->machime
z->y->x
假設d是最深層的巢狀子狀態,可以從d跳轉到y。首先要跳出d(執行d的exit action),依次跳出c,b,a。
不會離開innermostcommonouter狀態,進入x(執行x的entry action),進入y。
6. 監護條件
當乙個事件發生時,根據乙個條件表示式的bool值,決定此轉換的目標。最好的監護條件實現是if語句或者swich語句。boost提供custom_reaction<>自定義轉換機制,方便實現監護條件。
struct a : sc::******_state{
typedef sc::custom_reaction< evt > reactions;
sc::result react( const evt &evt )
//實現transition action
cout<<"transition action called"if (evt.m_raised_salary > 0){
return transit< c >(); //跳轉到狀態c
if (evt.m_raised_salary < 0){
return transit< b >(); //跳轉到狀態b
else{
return discard_event(); //什麼也不做
7. 轉移動作transition action
同乙個轉移關聯的動作。可以用custom_reaction<>機制實現。也可以用下述方法實現。
struct a : ******_state{
typedef transition< evt, b, s, &s::transtion_action > reactions;
其中,s要求至少是狀態a,b的innermostcommonouter,其outer環境也可以,當然狀態機m更可以。
struct s : sc::state_machine< s, 。。。 > {
void transtion_action(const evt &){ //transtion_action必須是這樣的函式簽名。
std::cout<<"s::transtion_action() called"<8. 投遞事件
最簡單是process_event函式
s s;
s.initiate();
s.process_event(evt());
事件首先被投遞給最深層的當前子狀態,讓後向外層投遞。
假設c->b->a,其中c是當前最深子狀態,並且abc三者都定義了對事件evt的轉移規則。
則c先獲得事件evt的處理。一般來說b,a將不能感知到事件。
c可以呼叫forward_event()將事件拋給b處理。這是當c不能處理乙個事件x(未定義狀態轉移)時,預設行為(拋給直接上級狀態處理)。
9. 進入/退出動作
struct a : ******_state{
a(){
std::cout<<"a建構函式被呼叫, entry action"<~a(){
std::cout<<"~a析構函式被呼叫,exit action"《使用建構函式和析構函式實現了狀態的進入,退出action
10. 歷史狀態
struct a : ******_state{
狀態a有乙個特殊的偽子狀態---淺歷史狀態。其初始值可以認為是a1(等於初始子狀態)。
當從a轉移出後,能記住最後乙個直接子狀態例如:a9。
當從別處重新回到a狀態時,能直接進入到a9。(而不是進入初始子狀態。)
「淺」是指:只記住a的直接子狀態;「深」是指:能記住a的最深的巢狀子狀態。
struct x : ******_statetypedef sc::transition> reactions;
回到a,進入歷史狀態
11. 多事件
typedef boost::mpl::list<
sc::transition< evt1, b >
sc::transition< evt2, c >
> reactions;
乙個狀態對多種事件的反應規則
12. 標頭檔案
#include
#include
#include
#include
#include
#include
#include
#include
13. 延遲事件
struct b : sc::******_state{
typedef sc::deferral< evtdefer > reactions;
處於b狀態時,暫時不能處理evtdefer,但是希望離開b狀態時,才處理事件evtdefer。
延遲事件同post_event()不同之處在於,post_event能把事件放入狀態機主事件佇列,在action執行完成後,
就會立刻執行被post的事件(沒有等待b結束,這個重要條件)
14. 狀態機terminate()
terminate()會造成狀態機離開當前活動狀態,到達偽終態。
typedef boost::mpl::list<
sc::transition< evt2a,a >,
sc::deferral< evtdefer >,
sc::termination< evtkill >
> reactions;
或者sc::result a::react( const evtkill & )
return terminate();
15. sc::result
sc::result a::react( const evt& )
return discard_event(); //忽略事件
sc::result a::react( const evt& )
return forward_event(); //請求向上級狀態處理此事件
sc::result a::react( const evt& )
return transit(); //轉移到b狀態
sc::result a::react( const evt& )
return terminate(); //狀態機自殺
16. 查詢狀態機是否在執行
bool lb = s.terminated(); //其中s是乙個狀態機物件
狀態機 狀態機0
近半年都忙於做專案,沒有太多的時間去整理和總結在專案中用過的技術 個人還是覺得技術需要總結提煉和沉澱的,忙到沒時間去總結提公升其實不 是什麼好事,這次講下狀態機,在戰鬥型別的遊戲中角色有多種不同的狀態,而狀態的切換錯綜複雜,23種設計模式中有一種模式叫做狀態模式,不過 這種模式是把狀態切換條件放到各...
python 狀態機 Python 狀態機
class statemachine def init self self.handlers 狀態轉移函式字典 self.startstate none 初始狀態 self.endstate 最終狀態集合 引數name為狀態名,handler為狀態轉移函式,end state表明是否為最終狀態 de...
狀態機小記
工作上有個功能模組用到了類似狀態機的東東,於是上網科普了一番。狀態機是由一系列輸入驅動,然後系統由其中一種狀態轉換為另一種狀態並產生某種輸出,這樣子的乙個系統叫做狀態機。狀態機分為兩種,一種是輸出只和系統狀態有關,叫做摩爾狀態機,另一種是輸出和輸入以及系統狀態都相關,叫做公尺莉狀態機。有關輸入 狀態...