A UML 狀態圖 是一種強大的視覺化工具,透過展示系統如何根據事件在不同狀態之間轉換,來模擬系統的動態行為。它記錄了物件或流程的生命周期——顯示其可能的狀態 處於 中,什麼觸發了變更,以及狀態變更期間發生的動作——使其成為理解複雜系統(如交通信號燈、自動販賣機、登入流程或遊戲角色)的理想工具。透過專注於狀態(例如「紅色」、「等待付款」或「跳躍」)、轉換(由事件驅動,如「計時器到期」或「按鈕按下」)以及條件(守衛),狀態圖提供了清晰性,避免邏輯漏洞,並成為設計與程式碼的基礎。無論你是初學者學習系統建模,還是開發者打造穩健的軟體,掌握狀態圖將使你具備以精確與清晰的方式思考、設計和溝通系統行為的能力。

💡 目標:學習如何使用狀態機來模擬現實世界中的系統——從構想到清晰且專業的圖示。
🔑 你必須首先理解的關鍵概念
| 概念 | 它的含義 | 為何重要 |
|---|---|---|
| 狀態 | 系統所處的條件或情境(例如 紅色, 等待投入硬幣) |
顯示任何時刻正在發生的事 |
| 事件 | 觸發變化的某種事物(例如 投入硬幣, 計時器到期) |
導致狀態之間的移動 |
| 轉換 | 從一個狀態指向另一個狀態的箭頭 | 透過事件連結狀態 |
| 初始狀態 | 起始點 (●) | 總會有一個 |
| 終止狀態 | 流程結束 (○) | 可選 — 不一定需要 |
| 守衛 [條件] | 轉移發生時必須為真的條件 | 增加邏輯(例如:金額足夠嗎?) |
| 動作 / 進入/執行 | 進入、進行中或離開狀態時會發生什麼 | 為狀態增加行為 |
📌 試著思考:
「這個系統可以處於 X 種狀態。
當 Y 發生時,它會轉移到 Z.”
這就是一個狀態機!
🛠 步驟 0 – 思維模式:提出這些問題
在繪製任何內容之前:
-
這個事物可能處於哪些 明顯不同的狀態 這個事物可能處於的狀態?
-
什麼 事件(使用者操作、時間、錯誤)會導致變更嗎?
-
它能同時處於兩個狀態嗎?(不行 → 基本的狀態機是互斥的。)
👉 範例:一個燈的開關不是開啟就是關閉絕不會同時兩者皆是。
🧩 步驟 1 – 選擇一個具體的事物來建模
✅ 適合初學者的選擇:
-
閘門(鎖定/解鎖)
-
交通號誌(紅/綠/黃)
-
自動販賣機
-
登入系統
-
訂單狀態:
已建立 → 已付款 → 已出貨 → 已送達
❌ 避免:
-
「整個線上商店」→ 過於龐大
-
「使用者體驗」→ 過於模糊
✏️ 從簡單開始。先掌握小範例。
📌 步驟 2 – 列出狀態(使用名詞或現在分詞)
寫下4到8個實際的狀態.
使用形容詞或現在分詞來讓它看起來像是一種狀態:
-
紅色 -
綠色 -
黃色 -
等待硬幣 -
發放物品 -
準備中 -
付款失敗
✅ 提示:如果你有超過 10 個狀態 → 將系統拆分成較小的部分。
🖌 步驟 3 – 將狀態繪製為圓角矩形
使用圓角矩形:
[ 紅色 ]
[ 綠色 ]
[ 等待硬幣 ]
✅ 工具:
draw.io / diagrams.net(最佳免費選擇)
Excalidraw(手繪風格)
PlantUML(基於文字 → 易於版本控制)
Lucidchart / Miro
🔷 步驟 4 – 添加初始狀態(黑色圓點)
繪製一個填滿的黑色圓形並以箭頭指向第一個狀態。
[*] --> 紅色
這個
[*]代表「初始狀態」——這是起始點。
➡️ 步驟 5 – 使用事件繪製轉移
針對每個狀態,請問:
「在此處會發生什麼事情,讓我離開這個狀態?」
以以下內容標示箭頭:
事件 [守衛] / 動作
🔹 從簡單開始:僅需
事件或事件 / 動作
常見事件:
-
投入硬幣 -
計時器到期 -
付款失敗 -
按鈕被按下 -
行人按鈕 -
逾時
✅ 步驟 6 – 添加最終狀態(可選)
使用一個粗邊圓形作為最終狀態。
[已交付] --> [●]
並非所有系統都有最終狀態(例如永遠運行的交通信號燈)。
🔁 步驟 7 – 添加現實中的邊界情況
詢問:
-
可以取消嗎?→新增
取消→ 回到空閒 -
時間會結束嗎?→
逾時→ 回到等待 -
會失敗嗎?→新增
錯誤→返回開始 -
它能保持在同一狀態嗎?→自轉移
範例:自轉移(增加更多金額):
[有信用] -- 投入硬幣 --> [有信用]
🚦 步驟 8 – 使用守衛進行智慧邏輯
當相同的事件導致不同的結果,使用守衛.
範例:
如果你按下
pedButton期間綠色,但目前還沒有需求 → 你進入綠色且行人等待.
但如果需求已經設定 → 你只需忽略它。
[車輛綠燈] --> [車輛綠燈] : pedButton / 設定需求 = true
這是一個帶有動作的自轉移—— 不是新的狀態。
🎯 步驟 9 – 添加進入/執行/退出動作(可選但強大)
您可以在狀態框內撰寫動作狀態框內:
[紅色]
進入 / 開啟紅燈
退出 / 關閉紅燈
執行 / 等待 30 秒
有助於釐清行為,而不會使轉移變得混亂。
✅ 步驟 10 – 最終檢查清單(自我提問)
| ✅ 檢查 | 為何重要 |
|---|---|
| 只有一個初始狀態嗎? | 必須從某處開始 |
| 所有狀態都有外出箭頭(最終狀態除外)? | 沒有死路 |
| 沒有無法到達的狀態嗎? | 每個狀態都應該可以到達 |
| 轉移是否以事件標記? | 明確的因果關係 |
| 箭頭不表示「前往 X」——箭頭僅顯示方向 | 更乾淨 |
| 是否包含取消 / 超時 / 錯誤路徑? | 真實系統會失敗——請做好準備 |
| 圖表是否能完整顯示在螢幕上? | 清晰且易讀 |
📋 快速參考:PlantUML 語法(UML 標準)
| 符號 | 含義 |
|---|---|
[*] |
初始狀態 |
[*] --> 狀態 |
從此狀態開始 |
狀態 --> 狀態 |
轉移 |
事件 [保護條件] / 動作 |
箭頭上的標籤 |
狀態 "名稱" |
命名狀態(可選) |
狀態 "X" 為 X |
複雜名稱的別名 |
狀態右側的註解 |
註解框 |
🎯 範例 1:簡單的交通號誌(三狀態循環)
非常適合完全的新手。
🧠 實際應用:
-
基本交通號誌循環:紅色 → 綠色 → 黃色 → 紅色
✅ 狀態:
-
紅色 -
綠色 -
黃色
🔄 事件:
-
計時器到期(30 秒後、25 秒後、5 秒後)
🛠 PlantUML 程式碼(可複製貼上):

@startuml
skinparam monochrome true
[*] --> 紅色
紅色 --> 綠色 : after(30s)n計時器到期
綠色 --> 黃色 : after(25s)n計時器到期
黃色 --> 紅色 : after(5s)n計時器到期
紅色 : entry / 開啟紅燈
綠色 : entry / 開啟綠燈
黃色: entry / 開啟黃燈
note right of 紅色
車輛必須停下
end note
note right of 綠色
車輛可以通行
end note
note right of 黃色
準備停下
end note
@enduml
✅ 如何使用:
前往 https://www.plantuml.com/plantuml,貼上程式碼,然後按「產生」。
🖼️ 輸出:一個乾淨、具有動畫效果的狀態機圖。
🎯 範例 2:具現實感的交通號誌,帶有行人請求功能
這最具教育意義的版本—— 引入了守衛、自轉移和複雜邏輯。
🧠 實際應用:
-
行人按下按鈕以穿越道路。
-
如果有人等待,信號燈會延長等待時間。
-
綠燈結束後,會轉為黃燈 → 紅燈 → 行人通行 → 閃爍的禁止通行 → 回到綠燈。
📌 關鍵狀態:
-
車輛綠燈-無需求—— 綠燈,無行人等待 -
車輛綠燈-行人等待—— 綠燈,有人按下了按鈕 -
車輛黃燈—— 黃燈(禁止通行) -
全紅—— 安全緩衝(極短) -
行人通行—— 行人通行標誌亮起 -
行人清場—— 閃爍的禁止通行(清場時間)
🧩 關鍵轉移:
-
行人按鈕—— 如果未等待 → 設定需求 -
定時器到期—— 轉為黃燈(若綠燈時間已達) -
行人按鈕—— 在黃燈/紅燈期間 → 記住需求 -
計時器行走→ 轉至閃爍的「禁止穿越」 -
計時器清場→ 重置並返回綠燈
🚨 注意:此版本使用守衛條件與自我轉移,顯示為何狀態機如此強大.
✅ PlantUML 程式碼(完全可運作,可直接使用):

@startuml
skinparam monochrome true
skinparam shadowing false
skinparam dpi 120
[*] --> VehicleGreen_NoDemand
state "車輛綠燈n(無行人需求)" as VG_No
state "車輛綠燈n(行人等候中)" as VG_Wait
state "車輛黃燈" as VYellow
state "全紅n(安全緩衝)" as AllRed
state "行人行走" as PedWalk
state "行人清場n(閃爍禁止穿越)" as PedClear
VG_No --> VG_Wait : pedButton / setPedDemand = true
VG_No --> VYellow : after(35s)nor (pedDemand && minGreenTimeMet)
VG_Wait --> VYellow : after(45s)n行人等候時延長綠燈
VG_Wait --> VG_Wait : pedButton / 忽略(已等候)
VYellow --> AllRed : after(4s)
AllRed --> PedWalk : after(1s)
PedWalk --> PedClear : after(10s)n行走時間結束
PedClear --> VG_No : after(5s)n清場完成n/ resetPedDemand
note bottom of VG_No
正常運作
無行人需求
end note
note right of PedClear
行人完成穿越
閃爍禁止穿越訊號
end note
note right of VG_Wait
行人按下按鈕
綠燈最多延長10秒
end note
note right of VYellow
準備停止
車輛燈號切換
end note
note right of PedWalk
行走訊號亮起
行人可穿越
end note
@enduml
💡 為何此版本優於簡單版本?
顯示現實世界的複雜性
示範守衛條件 (
若行人需求存在)使用自我轉移 (
VG_Wait --> VG_Wait)模擬真實行為:綠燈可延長!
明確區分車輛 和 行人 邏輯
🎓 推薦練習題(按順序完成)
| # | 範例 | 時間 | 學到的技能 |
|---|---|---|---|
| 1 | 燈開關(開 ↔ 關) | 5 分鐘 | 基本轉換 |
| 2 | 閘機(鎖定 ↔ 解鎖) | 10 分鐘 | 事件、守衛 |
| 3 | 交通燈(三狀態循環) | 10 分鐘 | 定時器、進入動作 |
| 4 | 自動販賣機(等待 → 支付 → 出貨) | 15 分鐘 | 多個事件、金錢邏輯 |
| 5 | 登入(空白 → 輸入 → 提交 → 成功/失敗) | 15 分鐘 | 錯誤處理、最終狀態 |
| 6 | 訂單狀態(6 種狀態) | 20 分鐘 | 現實生活中的系統模擬 |
✅ 從 #1–3 開始在紙上或 draw.io 中進行。然後使用 PlantUML 進行剩下的部分。
🧠 成功的最後建議
-
從小處著手 —— 不要試圖一次包含所有內容。
-
使用真實名稱 —
等待硬幣,而不是狀態1. -
清楚標示轉移 —
按鈕被按下,逾時,付款失敗. -
先用手繪製 —— 然後轉為數位格式。
-
在腦中測試:「這個系統會卡住嗎?」→ 如果是,就增加一個轉移。
📌 總結:你的狀態機檢查清單
✅ 一個 [*] (初始狀態)
✅ 圓角矩形表示狀態
✅ 箭頭表示轉移
✅ 箭頭上的事件(30秒後, 行人按鈕)
✅ 必要時加上守衛條件([行人需求])
✅ 自轉移用於重複動作
✅ 進入/離開動作用於行為
✅ 清晰的版面,易讀的字型
🎯 最後的話:你已經準備好了!
你剛才學到了:
-
什麼是狀態機圖
-
如何以狀態與事件思考
-
如何繪製與閱讀像專家一樣
-
如何模擬真實系統例如交通號誌
-
如何使用 PlantUML撰寫乾淨且易於維護的圖表
🎉 你不僅僅在學習UML——你正在學習如何模擬真實系統一次一個狀態。
📌 下一步(你的學習路徑)
-
手繪三狀態交通號誌——不使用工具,僅用紙張。
-
試試PlantUML使用上方的程式碼——看看它如何呈現。
-
修改:更改等待時間。新增「緊急覆蓋」狀態。
-
試試自動販賣機→ 相同邏輯,但加入金錢因素。
-
繪製你自己的:一個遊戲角色(行走 → 跳躍 → 攻擊 → 死亡)。
💬 需要幫助嗎?試試這樣說:「我正在嘗試模擬一個[你的系統]——你能幫我建立一個狀態機嗎?」
🙌 最後的想法
🔄 所有會變化的東西——無論是燈、登入,還是訂單——都可以用狀態機來模擬。
你不需要是程式設計師也能理解它。你只需要問:問:「這個東西可能處於什麼狀態,又是什麼讓它改變?」
✅ 現在你已經知道如何建立專業且實用的狀態機圖——從初學者進階為自信的建模者。
🎉 祝你繪圖愉快!
如果需要可列印的PDF版本、測驗,或編碼挑戰來測試你的技能,請告訴我。