設計複雜系統不僅需要知道它們的功能,還需要理解何時它們何時執行。這正是狀態圖成為工程師與架構師不可或缺工具的原因。狀態圖,通常稱為狀態機圖,能以視覺方式呈現系統的動態行為。它描繪出系統運作的條件,以及對特定事件的反應方式。
無論您是在建模簡單的自動販賣機,還是分散式雲端基礎架構,清晰度都至關重要。本指南探討業界常用的標準符號,特別聚焦於UML(統一建模語言)與MSC(訊息序列圖)。我們將解析符號、語法與最佳實務,協助您建立能明確傳達意圖、無歧義的圖表。

🧩 什麼是狀態機圖?
狀態機圖用來模擬物件或系統組件的生命周期。它回答一些基本問題:
- 系統可能處於哪些不同的狀態?
- 什麼觸發了狀態之間的轉換?
- 狀態改變時會發生什麼(動作)?
- 起始點是什麼?什麼標示著結束?
與流程圖不同,流程圖著重於資料或控制在流程中的流動,而狀態圖則著重於實體的狀態。此區別對具有記憶或持續狀態的系統至關重要,例如認證系統、交通號誌控制器或網路協定。
🔍 UML狀態機符號:標準規範
統一建模語言(UML)是建模軟體系統最廣泛採用的標準。UML 2.x版本對狀態機圖進行了優化,以處理更複雜的場景。理解UML符號的核心元素,是掌握此技術的第一步。
1. 核心元素
每個狀態圖都依賴於幾個基礎元件,這些是您將反覆使用的構建模塊。
- 狀態:以圓角矩形表示。代表物件在滿足某個不變式、執行某項活動或等待事件發生時所處的狀態。
- 轉換:連接兩個狀態的有向線條。表示系統在事件觸發下,從一個狀態轉移到另一個狀態。
- 事件:觸發轉換的起因。可以是訊號、時間事件或呼叫。
- 保護條件:以方括號包覆的布林表達式
[ ]。只有當此條件為真時,轉換才會發生。 - 動作:在轉換過程中或處於某狀態時執行的活動。通常以斜線「/」後面標示
/.
2. 進入和退出點
狀態並非靜態;它們具有生命周期。當進入某個狀態時,會觸發特定動作。當退出該狀態時,則會發生其他動作。UML符號能清楚地捕捉這一生命周期。
- 進入動作(entry /):在進入狀態的瞬間立即執行。
- 執行活動(do /):在狀態保持活躍期間持續執行。這對於持續性流程非常有用,例如馬達旋轉或計時器運行。
- 退出動作(exit /):在離開狀態之前立即執行。
例如,在一個線上購物車情境中,進入處理狀態可能會觸發一個entry / validate_stock()動作。在此狀態期間,系統可能會執行一個do / update_inventory()迴圈。退出時,可能會觸發一個exit / send_confirmation().
3. 初始狀態與終止狀態
每個圖表都需要明確的起點和終點。這些以特定形狀表示,以區別於一般狀態。
- 初始狀態:一個實心黑圓圈。這是系統的起點。每個圖表只能有一個初始狀態。
- 終止狀態:一個黑圓圈被一個圓形輪廓包圍(靶心形)。這表示系統生命周期的結束。狀態機可以有多個終止狀態。
📡 MSC:訊息序列圖
雖然UML專注於單一物件或組件的狀態,但MSC(訊息序列圖)則專注於多個物件在時間上的互動。它們經常與狀態圖一起使用,或與狀態圖結合,以提供完整的視圖。
MSC符號特別適用於:
- 顯示組件之間交換訊息的順序。
- 識別時序約束和延遲。
- 顯示平行流程。
在MSC中,垂直線代表實例(物件),水平箭頭代表訊息。垂直軸代表時間向下流動。這補充了狀態圖,用以顯示誰發送了觸發狀態變化的事件。
🛠 記號比較表
為了讓區別更清楚,以下是標準建模記號中常見符號及其含義的分解說明。
| 符號形狀 | 名稱 | UML 含義 | 常見用法 |
|---|---|---|---|
| ●(實心圓圈) | 起始點 | 狀態機的起始 | 始終為第一個節點 |
| ◎(靶心) | 終止點 | 狀態機的結束 | 流程的終止 |
| ⬜(圓角矩形) | 狀態 | 物件的當前狀態 | 描述狀態(例如:開啟、關閉) |
| ➡️(箭頭) | 轉移 | 從一個狀態轉變到另一個狀態 | 連接狀態 |
| ◀(菱形) | 判斷節點 | 根據條件進行分支 | 守衛條件評估 |
| ⬤(小實心圓) | 歷史狀態 | 重新進入先前狀態 | 跳回你離開的位置 |
| 🔗(連結) | 合併 | 並行流程的合併 | 合併並發狀態 |
🚀 高級 UML 概念
一旦你掌握了基本概念,就可以使用高級 UML 功能來模擬更複雜的行為。這些概念允許層次結構和並發性,這對於現實世界中的系統至關重要。
1. 嵌套狀態(子狀態)
複雜狀態通常包含子狀態。例如,一個車輛狀態可能包含如引擎啟動, 引擎關閉,以及點火鑰匙插入。這稱為狀態層次結構。當父狀態處於活躍狀態時,子狀態也處於活躍狀態。這能減少圖表的雜亂,並清晰地顯示關係。
2. 正交區域(並發性)
如果這些狀態是正交的,單一物件可以同時處於多個狀態。這通過用實線將狀態框劃分為獨立區域來表示。例如,一個智慧型手機可以同時處於充電狀態,同時也處於螢幕開啟狀態。這些區域並行運行。
3. 虛擬狀態
虛擬狀態並非真正的狀態,而是協助管理流程的控制點。它們通常以特定符號繪製,但並不代表系統所處的某種靜態條件。
- 深度歷史: 回到該狀態的最後一個活躍子狀態。
- 淺層歷史: 回到該狀態的初始子狀態。
- 分叉: 將一個轉移拆分為多個並行轉移。
- 匯合: 等待多個並行轉移完成後才繼續。
📝 初學者最佳實務
繪製一個圖表是一回事;繪製一個優良圖表是另一回事。遵循以下指南,確保你的作品清晰易讀且易於維護。
- 保持狀態原子性: 一個狀態應代表單一明確的條件。避免在狀態名稱中加入複雜邏輯。
- 使用一致的命名規則: 建立命名規範(例如,狀態名稱始終大寫),以及轉移的命名方式(例如,以動詞為基礎)。
- 限制轉移的複雜度: 如果一個轉移擁有過多的守護條件,應考慮將其拆分為多個轉移或狀態。
- 避免跨參考: 儘量讓轉移保持在當前狀態範圍內。長距離跳轉至遠端狀態可能讓讀者感到困惑。
- 明確標示事件: 確保事件名稱具有描述性。不要使用
e1,而應使用user_login_attempt. - 記錄動作: 不僅僅畫出線條;還需在線條上記錄動作。傳遞了哪些資料?哪些內容被更新?
⚠️ 常見錯誤應避免
即使是經驗豐富的建模者也會犯錯。了解常見的陷阱可以幫助您在審查過程中節省時間。
- 死結: 確保每個狀態都有一條通往退出狀態或另一個狀態的有效路徑。若某狀態沒有任何出站轉移(除了終止狀態外),則可能導致死結。
- 無法到達的狀態: 檢查每個狀態是否都能從初始狀態到達。若某狀態孤立存在,則表示設計中可能存在錯誤。
- 遺漏錯誤處理: 實際系統會遇到故障。確保您的圖表能涵蓋錯誤事件,並包含轉移到錯誤或恢復狀態的轉移。
- 過度設計: 不要立即建模每一個可能的邊界情況。應從正常流程開始,再逐步增加複雜性。
🔗 超越UML:哈雷狀態圖
在UML成為標準之前,大衛·哈雷(David Harel)提出了狀態圖(Statecharts)。UML狀態機中的許多功能都直接源自哈雷的工作。若您遇到舊版文件,可能會看到:
- AND狀態: 與UML正交區域類似。
- 互斥(XOR)狀態: 一組狀態,其中僅能有一個處於活躍狀態。
理解這些來源,有助於閱讀較舊的技術規格,或在使用早於UML 2.x的特定領域建模語言時提供幫助。
🛡️ 安全性與狀態建模
狀態圖對於安全性分析也至關重要。透過繪製驗證系統的狀態,您可以識別出:
- 敏感資料可存取的狀態。
- 可能導致權限提升的轉移。
- 缺乏適當驗證保護的狀態。
例如,在支付網關中,確保「待處理」狀態無法直接轉移到「已完成」狀態,除非有「成功」事件,這是一項安全要求。透過視覺化此流程,可使審計更為容易。
📌 重點總結
- 狀態圖用來模擬系統隨時間變化的動態行為。
- UML 提供了狀態、轉移和事件的標準符號。
- MSC 透過顯示互動序列來補充狀態圖。
- 偽狀態和嵌套狀態允許進行複雜且層級化的建模。
- 清晰的命名與邏輯流程比複雜的圖形更重要。
- 在實作之前,務必驗證死鎖與無法達成的狀態。
掌握這些符號需要練習。從簡單的系統開始,應用規則,並逐步增加複雜度。目標不是創造完美的圖表,而是創造能減少歧義並提升團隊內部溝通的圖表。
請記住,圖表的價值在於它能否被他人閱讀和理解。保持簡潔、保持一致,並專注於你試圖定義的行為。有了這些工具在手,你將能充分應對系統建模的挑戰。











