有限狀態機(Finite State Machine, FSM) - Bear Wang 🐻
===
[TOC]
## What is ==狀態機==?
> **狀態機**是一個抽象的機器或系統模型,也是一個強大的思維工具
狀態機就像是一個會變化的系統,它可以處於不同的單一狀態,根據發生的事件或特定條件,從一個狀態切換到另一個。
> :包含**狀態**、**事件**、**轉換**和**動作**四個基本要素。
如果以不同的分類標準來定義的話,有各種不同的狀態機分類。
🚩 **以狀態==數量==分類的狀態機有:**
:::info
### **有限狀態機(Finite State Machine,FSM)**
---
- 定義:
- 具有**有限數量**的狀態
- 狀態轉換規則明確且固定
- 所有可能的狀態都可以預先定義
- 運用情境:
- 訂單處理系統(待付款→已付款→已發貨→已完成)
- 遊戲狀態控制(開始→暫停→結束)
- 電梯控制系統(上行→停止→下行)
- 交通信號燈控制(紅→黃→綠)
- etc ...
:::
:::info
### **無限狀態機(Infinite State Machine,ISM)**
---
- 定義:
- 可能具有無限數量的狀態
- 狀態數量是動態的或不可預知的
- 轉換規則可能動態變化
- 運用情境:
- 計數器系統(數值可以無限增長)
- 動態內存管理(內存分配狀態)
- 實時數據流處理(持續接收新數據)
- etc ...
:::
:::warning
**主要差異**
---
| 特點 | 有限狀態機(FSM) | 無限狀態機(ISM) |
| --- | --- | --- |
| 狀態數量 | 有限且固定 | 無限或動態 |
| 可預測性 | 高 | 相對較低 |
| 實現複雜度 | 較簡單 | 較複雜 |
| 資源消耗 | 較少 | 較多 |
| 適用場景 | 明確且有限的業務流程 | 動態變化的系統 |
:::
> 實務上 我們通常在說狀態機的時候泛指 **有限狀態機**
## Why do we need to learn about "有限狀態機"
學習有限狀態機(FSM)的核心價值可以總結為三大面向:
#### 1. 系統思維的建立
- 提供清晰的邏輯框架,將複雜問題分解為可理解的狀態
- 培養系統性思考方式,強化問題分析能力
- 有助於預測和控制系統行為,提升決策品質
#### 2. 實務應用的效益
- 程式設計更有條理,維護和除錯更容易
- 需求分析和流程設計更準確
- 系統擴展性好,新功能整合更順暢
- 提升團隊溝通效率,降低誤解成本
#### 3. 跨領域的通用價值
- 從工程師到產品經理都能受益
- 適用於軟體開發、流程管理、產品設計等多個領域
- 提供通用的思維模型,促進跨部門協作
- 有助於業務流程優化和風險管理

簡單來說,FSM不只是一個技術概念,而是一種強大的思維工具,
幫助我們將複雜的問題或系統分解成清晰的==狀態==和==轉換規則==,不僅適用於程式設計,更可應用於生活中各種場景的系統化思考和問題解決。

## What is 有限狀態機 (Finite State Machine, FSM)
:::info
### 定義:
---
- 具有==有限==數量的狀態
- 狀態轉換規則明確且固定
- 所有可能的狀態都可以預先定義
:::
:::info
### 基本要素:
---
- **狀態(States)**:
系統擁有明確且有限數量的狀態,每個狀態代表系統在特定時刻的情況。
- **事件/轉換條件(Events / Transition Condition)**:
系統能夠識別並接收預先定義的事件或輸入,這些事件會觸發狀態的改變。
- **轉換(Transitions)**:
系統遵循固定且明確的規則,根據當前狀態和接收到的事件決定如何轉換到下一個狀態。
- **動作(Actions)**:
在特定狀態下或狀態轉換過程中,系統會執行預先定義的相應動作或行為。
:::
:::info
#### 簡例說明
用按鈕或感應器控制大門的打開或關閉。
---

| 項目 | 說明 | 解釋 |
|------------------------------|------------------------------|-------------------------------------------------------------|
| **狀態 (State)** | - 門開著<br>- 門關著 | - 狀態代表系統的當前情況或條件<br>- 系統在任一時刻只能處於一個狀態<br>- 門只能是「開啟」或「關閉」<br>- 門系統永遠處於這兩個狀態之一 |
| **事件 (Event)** `轉換條件` | - 開門指令信號<br>- 關門指令信號 | - 事件是觸發狀態改變的**外部輸入**<br>- 可能來自按鈕、感應器或刷卡等<br>- 事件促使系統從一個狀態轉換到另一個 |
| **轉換 (Transition)** | - 門關著 → 門開著 <br>- 門開著 → 門關著 | - 定義了狀態之間如何切換<br>- 箭頭指示狀態改變的方向<br>- 轉換必須有明確的觸發事件 |
| **動作 (Action)** | - 門開著狀態:啟動開門馬達<br>- 門關著狀態:啟動關門馬達 | - 進入某狀態時系統執行的具體行為<br>- 例如進入「開啟狀態」時,馬達自動啟動<br>- **動作是系統行為自動執行的,不需要額外觸發** |
---
上面的例子是一個最基本的FSM,他滿足了FSM的基本條件
- 兩個明確的狀態
- 清晰的轉換條件
- 狀態間的轉換關係
- 每個狀態的進入動作
:::
:::spoiler 🫤: 老師~ [事件] 和 [動作] 容易搞混怎麼辦?
:::danger
#### 溫腥小提醒
容易搞混的 **事件** `Event/Transition Condition` v.s. **動作** `Action` 要怎麼分辨呢?
---

🤨 可以看到這個示意圖的 **[開門]** 與 **[關門]** 同時是**動作**,也是**事件**!?
那到底他們的差別是什麼呢?
| 類別 | 說明 | 具體表達方式 |
|--------|------------------------------|------------------------------|
| **事件 (Events)** | - 這裡`開門` 和 `關門`:「觸發條件」 <br>- 事件是**輸入**`是促使狀態改變的觸發因素`<br>- ex.按鈕、感應器、遙控信號etc. | - **收到開門信號**(而不是簡單的`開門`)<br>- **收到關門信號**(而不是簡單的`關門`) |
| **動作 (Actions)** | - 這裡`開門` 和 `關門`:「系統行為」<br>- 動作是**輸出**`進入狀態後系統要做的行為`<br>- ex.啟動馬達、提示聲音etc. | - **啟動開門馬達**(具體的系統行為)<br>- **啟動關門馬達**(具體的系統行為) |
---
:bulb:
- 事件(Event / Transition Condition) 是**系統的輸入(接收)**
- 動作(Action) 是**系統的輸出(執行)**
兩者雖然可能描述相似的概念,但在FSM中扮演不同的角色
:::
:::info
### 動作(Action)
而 **動作**, 在不同時機執行的動作又可以分成四種
---
- **進入動作** (Entry Action):
進入這個狀態時,會執行什麼工作?
- **離開動作** (Exit Action):
離開這個狀態時,會執行什麼工作?
- **輸入動作** (Input Action):
處於某狀態時,收到事件會執行什麼動作? `(即執行動作但不轉變狀態)`
- **轉移動作** (Transition Action):
轉移狀態過程中,會執行什麼動作?
---
- FSM的動作執行時機分兩種狀況來說明:
1. 狀態會改變
2. 狀態不改變


---
#### 狀態機執行流程說明:
- 系統處於某個狀態時,可以接收各種事件
- 根據接收到的事件,決定是否需要改變狀態
- 如果需要改變狀態,依序執行以下動作:
1. [輸入動作] `在原狀態下` 接收到事件執行
2. [離開動作] `在原狀態下` 狀態改變前執行
3. [轉移動作] `此過程中狀態逐漸改變` ==不屬於原狀態也不是新狀態==
4. [進入動作] `在新狀態下`
- 如果不需要改變狀態,則只執行[輸入動作]
- 完成動作執行後,系統進入新狀態或維持原狀態
---
#### 重要提示:
1. 當需要狀態改變時(路徑A):轉移動作是必要的,其他動作皆為可選
2. 當不需要狀態改變時(路徑B):只執行輸入動作,不需要其他動作
3. 執行順序(路徑A):輸入動作 → 離開動作 → 轉移動作 → 進入動作
:::
## Example
:::success
### :traffic_light: 範例
#### 需求
我要做一個紅綠燈功能。
需要具備紅、黃、綠三種燈號,且必須能夠依序自動切換燈號。
- 紅燈亮40秒
- 紅燈轉黃燈,黃燈亮5秒
- 黃燈轉綠燈,綠燈亮60秒
- 綠燈轉黃燈,黃燈亮10秒
- 黃燈轉回紅燈,循環重新開始
---
#### 元素
1. **狀態 (States)**:
系統在任何時刻都只能處於三種狀態之一:紅燈、黃燈或綠燈
- 紅燈 :heart:
- 黃燈 :yellow_heart:
- 綠燈 :green_heart:
2. **事件 (Events / Transition Condition)**:
系統通過計時器觸發狀態改變
- 紅燈計時器到達40秒
- 黃燈計時器到達5秒(紅轉綠時)
- 綠燈計時器到達60秒
- 黃燈計時器到達10秒(綠轉紅時)
3. **轉換 (Transitions)**:
每次轉換都遵循固定的順序和時間
- :heart: 紅燈 (40秒後)→ :yellow_heart: 黃燈
- :yellow_heart: 黃燈 (5秒後)→ :green_heart: 綠燈
- :green_heart: 綠燈 (60秒後) → :yellow_heart: 黃燈
- :yellow_heart: 黃燈(10秒後) → :heart: 紅燈
4. **動作 (Actions)**:
系統在不同時機執行四種動作:
- 輸入動作:檢查計時器、更新顯示
- 離開動作:關閉當前燈號、記錄狀態
- 轉移動作:執行實際的燈號切換
- 進入動作:開啟新的燈號、設定計時器
:::
:::spoiler 紅綠燈範例圖示

#### [紅綠燈程式碼範例](https://codesandbox.io/p/devbox/you-xian-zhuang-tai-ji-ftm-example-vpgszm?file=%2Fsrc%2FTrafficLight.tsx%3A31%2C7-31%2C18)
:::
## 延伸:設計模式 v.s 有效狀態機
> 在程式設計中,有限狀態機(Finite State Machine, FSM) 是一種用於系統狀態轉換的方式,特別適用於行為依賴於內部狀態的應用場景。許多設計模式與 FSM 的概念相似或直接應用於 FSM 的實作,以下是幾種最相關的設計模式:
:::info
### **1\. 狀態模式(State Pattern)**
**關聯性:**
狀態模式直接對應 FSM,透過定義不同的「狀態類別」,讓物件可以在不同狀態間切換,避免使用大量的 `if-else` 或 `switch-case` 來處理狀態變化。
**範例應用:**
- 設計遊戲角色的狀態(如「行走」、「攻擊」、「跳躍」)。
- 管理 UI 組件的不同狀態(如「開啟」、「關閉」、「懸停」)。
---
### **2\. 策略模式(Strategy Pattern)**
**關聯性:**
策略模式與 FSM 相似之處在於,它允許在不同情境下選擇不同的行為,但它更側重於「可變行為」而非「狀態轉換」。
**範例應用:**
- 根據不同的環境選擇不同的運算演算法(如 AI 行為決策)。
- 設計支付方式(如信用卡、PayPal、比特幣)。
---
### **3\. 命令模式(Command Pattern)**
**關聯性:**
命令模式允許將請求封裝為物件,可以與 FSM 結合,讓狀態機在不同狀態下選擇適當的命令來執行。
**範例應用:**
- 遊戲角色的技能切換(不同狀態執行不同指令)。
- GUI 按鈕的點擊行為(不同狀態觸發不同動作)。
---
### **4\. 觀察者模式(Observer Pattern)**
**關聯性:**
FSM 的狀態改變時,可能需要通知其他模組或組件進行相應動作,這與觀察者模式的機制相符。
**範例應用:**
- 當玩家的生命值變化時,UI 生命條也跟著變動。
- 當電商庫存狀態變更時,通知用戶和供應商。
---
### **5\. 責任鏈模式(Chain of Responsibility Pattern)**
**關聯性:**
當 FSM 處理事件時,責任鏈模式允許請求沿著一系列處理器傳遞,直到找到適當的處理方式,類似於 FSM 的狀態轉移。
**範例應用:**
- 事件處理系統(不同狀態由不同的 handler 負責處理)。
- 訊息過濾機制(依據不同狀態篩選資訊)。
---
### 對應表

---
### **結論**
有限狀態機(FSM)在許多應用場景中至關重要,而設計模式提供了一些有組織的方法來實作 FSM。其中 **狀態模式** 是最直接的 FSM 具現化方式,而 **策略模式、命令模式、觀察者模式與責任鏈模式** 則提供了不同層面的輔助,讓 FSM 的設計更加靈活、可維護。根據具體需求,開發者可以選擇最合適的模式來實作高效且可擴展的狀態機系統。
:::
## 參考資源
- [Day 21:什麼是「有限狀態機」?](https://ithelp.ithome.com.tw/articles/10225343)
- [如何有邏輯的釐清事物的狀態](https://medium.com/pm%E7%9A%84%E7%94%9F%E7%94%A2%E5%8A%9B%E5%B7%A5%E5%85%B7%E7%AE%B1/%E5%A6%82%E4%BD%95%E6%9C%89%E9%82%8F%E8%BC%AF%E7%9A%84%E9%87%90%E6%B8%85%E4%BA%8B%E7%89%A9%E7%9A%84%E7%8B%80%E6%85%8B-f9fb59b15054)
- [Design Patterns](https://refactoringguru.cn/design-patterns)