標題: C++ 狀態機問題 [打印本頁]
作者: 51黑tt 時間: 2016-3-5 20:09
標題: C++ 狀態機問題
有限自動機(Finite Automata Machine)是計算機科學的重要基石,它在軟件開發領域內通常被稱作有限狀態機(Finite State Machine),是一種應用非常廣泛的軟件設計模式(Design Pattern)。本文介紹如何構建基于狀態機的軟件系統。
一、什么是狀態機
有限狀態機是一種用來進行對象行為建模的工具,其作用主要是描述對象在它的生命周期內所經歷的狀態序列,以及如何響應來自外界的各種事件。在面向對象的軟件系統中,一個對象無論多么簡單或者多么復雜,都必然會經歷一個從開始創建到最終消亡的完整過程,這通常被稱為對象的生命周期。一般說來,對象在其生命期內是不可能完全孤立的,它必須通過發送消息來影響其它對象,或者通過接受消息來改變自身。在大多數情況下,這些消息都只不過是些簡單的、同步的方法調用而已。例如,在銀行客戶管理系統中,客戶類(Customer)的實例在需要的時候,可能會調用帳戶(Account)類中定義的getBalance()方法。在這種簡單的情況下,類Customer并不需要一個有限狀態機來描述自己的行為,主要原因在于它當前的行為并不依賴于過去的某個狀態。
遺憾的是并不是所有情況都會如此簡單,事實上許多實用的軟件系統都必須維護一兩個非常關鍵的對象,它們通常具有非常復雜的狀態轉換關系,而且需要對來自外部的各種異步事件進行響應。例如,在VoIP電話系統中,電話類(Telephone)的實例必須能夠響應來自對方的隨機呼叫,來自用戶的按鍵事件,以及來自網絡的信令等。在處理這些消息時,類Telephone所要采取的行為完全依賴于它當前所處的狀態,因而此時使用狀態機就將是一個不錯的選擇。
游戲引擎是有限狀態機最為成功的應用領域之一,由于設計良好的狀態機能夠被用來取代部分的人工智能算法,因此游戲中的每個角色或者器件都有可能內嵌一個狀態機。考慮RPG游戲中城門這樣一個簡單的對象,它具有打開(Opened)、關閉(Closed)、上鎖(Locked)、解鎖(Unlocked)四種狀態,如圖1所示。當玩家到達一個處于狀態Locked的門時,如果此時他已經找到了用來開門的鑰匙,那么他就可以利用它將門的當前狀態轉變為Unlocked,進一步還可以通過旋轉門上的把手將其狀態轉變為Opened,從而成功地進入城內。
在描述有限狀態機時,狀態、事件、轉換和動作是經常會碰到的幾個基本概念。
狀態(State) 指的是對象在其生命周期中的一種狀況,處于某個特定狀態中的對象必然會滿足某些條件、執行某些動作或者是等待某些事件。
事件(Event) 指的是在時間和空間上占有一定位置,并且對狀態機來講是有意義的那些事情。事件通常會引起狀態的變遷,促使狀態機從一種狀態切換到另一種狀態。
轉換(Transition) 指的是兩個狀態之間的一種關系,表明對象將在第一個狀態中執行一定的動作,并將在某個事件發生同時某個特定條件滿足時進入第二個狀態。
動作(Action) 指的是狀態機中可以執行的那些原子操作,所謂原子操作指的是它們在運行的過程中不能被其他消息所中斷,必須一直執行下去。
二、手工編寫狀態機
與其他常用的設計模式有所不同,程序員想要在自己的軟件系統中加入狀態機時,必須再額外編寫一部分用于邏輯控制的代碼,如果系統足夠復雜的話,這部分代碼實現和維護起來還是相當困難的。在實現有限狀態機時,使用switch語句是最簡單也是最直接的一種方式,其基本思路是為狀態機中的每一種狀態都設置一個case分支,專門用于對該狀態進行控制。下面的代碼示范了如何運用switch語句,來實現圖1中所示的狀態機:
switch (state) {
// 處理狀態Opened的分支
case (Opened): {
// 執行動作Open
open();
// 檢查是否有CloseDoor事件
if (closeDoor()) {
// 當前狀態轉換為Closed
changeState(Closed)
}
break;
}
// 處理狀態Closed的分支
case (Closed): {
// 執行動作Close
close();
// 檢查是否有OpenDoor事件
if (openDoor()) {
// 當前狀態轉換為Opened
changeState(Opened);
}
// 檢查是否有LockDoor事件
if (lockDoor()) {
// 當前狀態轉換為Locked
changeState(Locked);
}
break;
}
// 處理狀態Locked的分支
case (Locked): {
// 執行動作Lock
lock();
// 檢查是否有UnlockDoor事件
if (unlockDoor()) {
// 當前狀態轉換為Unlocked
changeState(Unlocked);
}
break;
}
// 處理狀態Unlocked的分支
case (Unlocked): {
// 執行動作Unlock
unlock();
// 檢查是否有LockDoor事件
if (lockDoor()) {
// 當前狀態轉換為Locked
changeState(Locked)
}
// 檢查是否有OpenDoor事件
if (openDoor()) {
// 當前狀態轉換為Opened
changeSate(Opened);
}
break;
}
}
使用switch語句實現的有限狀態機的確能夠很好地工作,但代碼的可讀性并不十分理想,主要原因是在實現狀態之間的轉換時,檢查轉換條件和進行狀態轉換都是混雜在當前狀態中來完成的。例如,當城門處于Opened狀態時,需要在相應的case中調用closeDoor()函數來檢查是否有必要進行狀態轉換,如果是的話則還需要調用changeState()函數將當前狀態切換到Closed。顯然,如果在每種狀態下都需要分別檢查多個不同的轉換條件,并且需要根據檢查結果讓狀態機切換到不同的狀態,那么這樣的代碼將是枯燥而難懂的。從代碼重構的角度來講,此時更好的做法是引入checkStateChange()和performStateChange()兩個函數,專門用來對轉換條件進行檢查,以及激活轉換時所需要執行的各種動作。這樣一來,程序結構將變得更加清晰:
switch (state) {
// 處理狀態Opened的分支
case (Opened): {
// 執行動作Open
open();
// 檢查是否有激發狀態轉換的事件產生
if (checkStateChange()) {
// 對狀態機的狀態進行轉換
performStateChange();
}
break;
}
// 處理狀態Closed的分支
case (Closed): {
// 執行動作Close
close();
// 檢查是否有激發狀態轉換的事件產生
if (checkStateChange()) {
// 對狀態機的狀態進行轉換
performStateChange();
}
break;
}
// 處理狀態Locked的分支
case (Locked): {
// 執行動作Lock
lock();
// 檢查是否有激發狀態轉換的事件產生
if (checkStateChange()) {
// 對狀態機的狀態進行轉換
performStateChange();
}
break;
}
// 處理狀態Unlocked的分支
case (Unlocked): {
// 執行動作Lock
unlock();
// 檢查是否有激發狀態轉換的事件產生
if (checkStateChange()) {
// 對狀態機的狀態進行轉換
performStateChange();
}
break;
}
}
但checkStateChange()和performStateChange()這兩個函數本身依然會在面對很復雜的狀態機時,內部邏輯變得異常臃腫,甚至可能是難以實現。
在很長一段時期內,使用switch語句一直是實現有限狀態機的唯一方法,甚至像編譯器這樣復雜的軟件系統,大部分也都直接采用這種實現方式。但之后隨著狀態機應用的逐漸深入,構造出來的狀態機越來越復雜,這種方法也開始面臨各種嚴峻的考驗,其中最令人頭痛的是如果狀態機中的狀態非常多,或者狀態之間的轉換關系異常復雜,那么簡單地使用switch語句構造出來的狀態機將是不可維護的。
三、自動生成狀態機
為實用的軟件系統編寫狀態機并不是一件十分輕松的事情,特別是當狀態機本身比較復雜的時候尤其如此,許多有過類似經歷的程序員往往將其形容為"毫無創意"的過程,因為他們需要將大量的時間與精力傾注在如何管理好狀態機中的各種狀態上,而不是程序本身的運行邏輯。作為一種通用的軟件設計模式,各種軟件系統的狀態機之間肯定會或多或少地存在著一些共性,因此人們開始嘗試開發一些工具來自動生成有限狀態機的框架代碼,而在Linux下就有一個挺不錯的選擇──FSME(Finite State Machine Editor)。
歡迎光臨 (http://www.zg4o1577.cn/bbs/) |
Powered by Discuz! X3.1 |
主站蜘蛛池模板:
最新国产精品
|
国产欧美精品区一区二区三区
|
97久久精品午夜一区二区
|
97国产爽爽爽久久久
|
国产偷录视频叫床高潮对白
|
国产免费av网
|
久久精品国产久精国产
|
夜夜爽99久久国产综合精品女不卡
|
日日噜噜噜夜夜爽爽狠狠视频,
|
av在线一区二区
|
欧美日韩亚洲系列
|
www.天天操.com
|
亚洲一级二级三级
|
亚洲精品久久久久久首妖
|
日韩欧美在线观看视频网站
|
成人av观看
|
亚洲视频在线看
|
在线免费观看视频你懂的
|
成人一区二区三区在线观看
|
免费在线h视频
|
男人天堂网址
|
天天草天天爱
|
精产国产伦理一二三区
|
一区二区三区欧美大片
|
亚洲综合色丁香婷婷六月图片
|
日本a网站|
国产高清在线精品一区二区三区
|
国产在线精品一区二区
|
亚洲小视频在线观看
|
日韩成人影院
|
一区网站
|
丁香五月缴情综合网
|
久久久综合色
|
亚洲视频一区二区三区四区
|
超碰免费在
|
亚洲精品国产成人
|
琪琪午夜伦伦电影福利片
|
欧美成人精品在线观看
|
国产一二三区精品视频
|
自拍偷拍视频网
|
9191在线观看
|