設計模式之狀態機模式

一、狀態機模式介紹

狀態機模式(State Machine Pattern)是一種用于描述對象行為的軟件設計模式,屬于行為型設計模式。在狀態機模式中,對象的行為取決于其內部狀態,并且在不同的狀態下,對象可能會有不同的行為。這種模式通常涉及定義一組狀態以及狀態之間的轉換規則,從而實現對對象行為的精確控制。

1、狀態機模式的基本概念

狀態機類圖:

狀態機模式主要包含以下幾個要素:

  1. 狀態(State):表示對象所處的特定狀態。每個狀態都定義了對象在該狀態下的行為。
  2. 上下文(Context):上下文是包含狀態機的對象。它維護了當前狀態,并在狀態之間的轉換發生時更新狀態。
  3. 轉換(Transition):描述了對象從一個狀態轉移到另一個狀態的過程。它通常受到一些條件或觸發事件的影響。
  4. 動作(Action):動作是狀態轉換期間可能執行的操作或行為。這些動作可以是更新狀態、執行計算、發送消息等。

2、狀態機模式的特點

  1. 清晰的狀態管理:通過明確定義系統的所有可能狀態以及在這些狀態之間的轉換,幫助開發者清晰地管理和跟蹤系統的狀態。
  2. 簡化復雜邏輯:將復雜的條件分支邏輯轉換為狀態圖,使得邏輯更加直觀易懂。
  3. 易于維護和擴展:狀態機的結構使得對系統的修改和擴展變得更加容易。通過添加新的狀態和轉換規則,可以輕松適應需求的變化。
  4. 提高可測試性:由于狀態機的行為是預定義的,因此可以更系統地進行測試,有助于確保系統的正確性和可靠性。

3、狀態機模式的應用場景

狀態機模式在多種應用場景中都有廣泛的應用,包括但不限于以下幾個方面:

  1. 游戲開發:用于游戲中的角色狀態管理,如角色的移動、攻擊、防御等狀態。
  2. 嵌入式系統:用于描述設備的狀態和狀態轉移,如自動售貨機、電梯控制等。
  3. 網絡通信:用于管理網絡連接的狀態,如連接建立、數據傳輸、連接關閉等。
  4. UI設計:用于管理UI元素的交互邏輯,如按鈕的點擊狀態、表單的輸入驗證狀態等。

二、狀態機模式的實現例子

下面是一個簡單的Java狀態機模式例子。在這個例子中,我們將模擬一個簡單的交通信號燈系統,它有三種狀態:紅燈(Red)、綠燈(Green)、黃燈(Yellow)。每個狀態都有一個特定的行為,即打印出當前燈的顏色,并且每個狀態都可以轉換到下一個狀態。

首先,我們定義一個TrafficLightState接口,它表示交通信號燈的所有可能狀態:

public interface TrafficLightState {  void change(TrafficLightContext context);  
}

然后,我們為每種狀態實現這個接口:

public class RedLightState implements TrafficLightState {  @Override  public void change(TrafficLightContext context) {  System.out.println("紅燈亮");  context.setState(new GreenLightState());  }  
}  public class GreenLightState implements TrafficLightState {  @Override  public void change(TrafficLightContext context) {  System.out.println("綠燈亮");  context.setState(new YellowLightState());  }  
}  public class YellowLightState implements TrafficLightState {  @Override  public void change(TrafficLightContext context) {  System.out.println("黃燈亮");  context.setState(new RedLightState());  }  
}

接下來,我們定義TrafficLightContext類,它包含了當前的狀態,并且提供了一個方法來改變狀態:

public class TrafficLightContext {  private TrafficLightState state;  public TrafficLightContext() {  this.state = new RedLightState();  }  public void setState(TrafficLightState state) {  this.state = state;  }  public void change() {  state.change(this);  }  
}

最后,我們創建一個客戶端來模擬交通信號燈的狀態變化:

public class Client {  public static void main(String[] args) {  TrafficLightContext context = new TrafficLightContext();  // 模擬狀態變化  context.change();  context.change();  context.change();  context.change();  context.change();  }  
}

在這個例子中,TrafficLightContext類維護了當前的交通信號燈狀態,并且提供了一個change方法來改變狀態。每個狀態類都實現了TrafficLightState接口,并且在其change方法中定義了下一個狀態。客戶端通過調用TrafficLightContextchange方法來模擬交通信號燈的狀態變化。?

現實中的狀態轉變,比這個復雜多了,一個狀態節點可能有多個action操作,類似訂單狀態的流轉,無法直接套用狀態機模式,應該有記錄狀態變遷的全景圖(核心要素:當前狀態,當前狀態可選動作,動作執行后狀態遷移)。

以下是一個簡單的例子,記錄當前狀態,可選動作及執行動作后狀態的一個例子,用于約束狀態的變遷,。

package demo;import java.util.HashMap;
import java.util.Map;public class StateMachine {/*** key:當前狀態 ,value: Map<String, String>,可選的動作及后續狀態,key:xxxAction,value:nextState*/private Map<String, Map<String, String>> stateMap;public StateMachine() {stateMap = new HashMap<String, Map<String, String>>();// 初始狀態可以執行的Action及執行后的動作Map<String, String> initActionMap = new HashMap<String, String>();initActionMap.put("runAction", "run");stateMap.put("init", initActionMap);// run狀態下可以執行的動作Map<String, String> runActionMap = new HashMap<String, String>();runActionMap.put("stopAction", "stop");runActionMap.put("sleepAction", "sleep");runActionMap.put("endAction", "end");stateMap.put("run", runActionMap);// sleep狀態下可以執行的動作Map<String, String> sleepActionMap = new HashMap<String, String>();sleepActionMap.put("runAction", "run");stateMap.put("sleep", sleepActionMap);// stop狀態下可以執行的動作Map<String, String> stopActionMap = new HashMap<String, String>();stopActionMap.put("runAction", "run");stateMap.put("stop", stopActionMap);}public String getNextState(String curState, String action) {Map<String, String> curStateMap = stateMap.get(curState);if (curStateMap == null) {System.out.println("curState error");return "";}String nextState = curStateMap.get(action);if (nextState == null) {System.out.println("acction error");return "";}return nextState;}public static void main(String[] args) {StateMachine sm = new StateMachine();String nextState = sm.getNextState("init", "runAction");System.out.println(nextState);nextState = sm.getNextState("run", "stopAction");System.out.println(nextState);nextState = sm.getNextState("stop", "runAction");System.out.println(nextState);nextState = sm.getNextState("run", "endAction");System.out.println(nextState);}}

三、總結

????????狀態機模式是一種強大的工具,能夠幫助開發者在軟件開發中處理復雜的邏輯和狀態管理問題。通過明確定義系統的狀態和轉換規則,狀態機模式使得系統的行為更加清晰、可控和易于維護。同時,狀態機模式還具有廣泛的應用場景和靈活的實現方式,適用于多種復雜的軟件開發需求。

如果狀態模式對你有用,記得點贊收藏。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/41202.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/41202.shtml
英文地址,請注明出處:http://en.pswp.cn/web/41202.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32F103C8T6核心板原理圖和PCB分享

PCB圖 原理圖 資料下載地址&#xff1a; 原理圖PCB庫: https://545c.com/d/45573183-61875742-29897c?p7526 (訪問密碼: 7526)

[go-zero] 簡單微服務調用

文章目錄 1.注意事項2.服務劃分及創建2.1 用戶微服務2.2 訂單微服務 3.啟動服務3.1 etcd 服務啟動3.2 微服務啟動3.3 測試訪問 1.注意事項 go-zero微服務的注冊中心默認使用的是Etcd。 本小節將以一個訂單服務調用用戶服務來簡單演示一下&#xff0c;其實訂單服務是api服務&a…

Java 使用sql查詢mongodb

在現代應用開發中&#xff0c;關系型數據庫和NoSQL數據庫各有千秋。MongoDB作為一種流行的NoSQL數據庫&#xff0c;以其靈活的文檔模型和強大的擴展能力&#xff0c;受到廣泛歡迎。然而&#xff0c;有時開發者可能更熟悉SQL查詢語法&#xff0c;或者需要在現有系統中復用SQL查詢…

【ARMv8/v9 GIC 系列 5.6 -- GIC 超優先級中斷詳細介紹】

請閱讀【ARM GICv3/v4 實戰學習 】 文章目錄 Interrupt superpriority超優先級中斷的特性和應用Physical interface interrupt signalsPhysical Group 1 Non-NMI for Current Security StatePhysical Group 1 for Other Security State, or a Group 0 Non-NMIPhysical Group 1 …

進程控制-wait和waitpid進程回收

wait 阻塞函數 函數作用&#xff1a; 1. 阻塞并等待子進程退出 2. 回收子進程殘留資源 3. 獲取子進程結束狀態&#xff08;退出原因&#xff09; pid_t wait(int *wstatus); 返回值&#xff1a; ‐1 : 回收失敗&#xff0c;已經沒有子進程了 >0 : 回收子進程對應的…

一種非凸全變差正則化的信號降噪方法(以模擬信號和軸承振動信號為例,MATLAB)

以旋轉機械振動信號為例&#xff0c;由于旋轉機械運行中背景噪聲較強&#xff0c;振動信號需要進行降噪處理。常用的小波閾值降噪會在信號的不連續處產生虛假的波峰和偽吉布森震蕩&#xff0c;而奇異值分解SVD去噪容易產生虛假分量&#xff0c;全變差去噪則不會出現這樣的情況&…

美國大選特色

美國總統是間接民選的。選民不直接投票選舉總統&#xff0c;而是通過選舉一個稱為選舉人團&#xff08;Electoral College&#xff09;的機構成員來間接決定總統。具體過程如下&#xff1a; 1. **選民投票**&#xff1a;在11月的大選日&#xff0c;選民投票選舉他們所在州的選…

深入理解JS逆向代理與環境監測

博客文章&#xff1a;深入理解JS逆向代理與環境監測 1. 引言 首先要明確JavaScript&#xff08;JS&#xff09;在真實網頁瀏覽器環境和Node.js環境中有很多使用特性的區別。尤其是在環境監測和對象原型鏈的檢測方面。本文將探討如何使用JS的代理&#xff08;Proxy&#xff09…

MySQL之備份與恢復(九)

備份與恢復 從備份中恢復 更高級的恢復技術 復制和基于時間點的恢復使用的是相同的技術:服務器的二進制日志。這意味著復制在恢復時會是個非常有幫助的工具&#xff0c;哪怕方式不是很明顯。下面將演示一些可以用到的方法。這里列出來的不是一個完整的列表&#xff0c;但應該…

STM32-USART

本內容基于江協科技STM32視頻學習之后整理而得。 文章目錄 1. 串口通信協議1.1 通信接口1.2 串口通信1.3 硬件電路1.4 電平標準1.5 串口參數及時序1.6 串口時序 2. USART串口通信2.1 USART簡介2.2 USART框圖2.3 USART基本結構2.4 數據幀2.5 數據幀-配置停止位2.6 起始位偵測2.…

DP學習——簡單工廠模式

學而時習之&#xff0c;溫故而知新。 敵人出招&#xff08;使用場景&#xff09; 不同的業務場景下要創建不同的對象&#xff0c;但是這些對象又有共同的特點。如何復用代碼呢&#xff1f;你會想到&#xff0c;這些對象可以抽象出一個基類/抽象類就行了&#xff0c;那么隨著業…

【Python】一文向您詳細介紹 argparse中 action=‘store_true’ 的作用

【Python】一文向您詳細介紹 argparse中 action‘store_true’ 的作用 下滑即可查看博客內容 &#x1f308; 歡迎蒞臨我的個人主頁 &#x1f448;這里是我靜心耕耘深度學習領域、真誠分享知識與智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主簡介&#xff1a;98…

pdf怎么轉換成圖片格式文件,pdf文檔怎么轉換成圖片格式

在數字化時代&#xff0c;pdf文件轉換成圖片格式是一種常見的操作&#xff0c;無論是在工作還是日常生活中&#xff0c;我們總會遇到需要將pdf文件轉換為圖片的需求。這可能是因為圖片格式更易于分享、展示或編輯。那么&#xff0c;如何高效地將pdf轉換成圖片呢&#xff1f;本文…

圖神經網絡實戰(16)——經典圖生成算法

圖神經網絡實戰&#xff08;16&#xff09;——經典圖生成算法 0. 前言1. 圖生成技術2. Erd?s–Rnyi模型3. 小世界模型小結系列鏈接 0. 前言 圖生成算法是指用于創建模擬圖或網絡結構的算法&#xff0c;這些算法可以根據特定的規則和概率分布生成具有特定屬性的圖&#xff0c…

深度解析:如何利用Python高效挖掘SQLite潛力

Python與SQLite共舞&#xff1a;構建高效輕量級數據庫應用實戰 Python&#xff0c;作為一門優雅且強大的編程語言&#xff0c;搭配輕巧靈活的SQLite數據庫&#xff0c;無疑為我們提供了揮灑創意的完美畫布。今天&#xff0c;咱們就通過一個鮮活的案例&#xff0c;一起探索如何…

leetcode77組合——經典回溯算法

本文主要講解組合的要點與細節&#xff0c;以及回溯算法的解題步驟&#xff0c;按照步驟思考更方便理解 c和java代碼如下&#xff0c;末尾 給定兩個整數 n 和 k&#xff0c;返回范圍 [1, n] 中所有可能的 k 個數的組合。 你可以按 任何順序 返回答案。 具體要點&#xff1a; …

將大型語言模型模塊化打造協作智能體

B UILDING C OOPERATIVE E MBODIED A GENTS MODULARLY WITH L ARGE L ANGUAGE M ODELS 論文鏈接&#xff1a; https://arxiv.org/abs/2307.02485https://arxiv.org/abs/2307.02485 1.概述 在去中心化控制及多任務環境中&#xff0c;多智能體合作問題因原始感官觀察、高昂…

【機器學習】機器學習重塑廣告營銷:精準觸達,高效轉化的未來之路

&#x1f4dd;個人主頁&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f339; ?目錄 &#x1f4d2;1. 引言&#x1f4d9;2. 機器學習基礎與廣告營銷的結合&#x1f9e9;機器學習在廣告營銷中的核心應用領域&#x1f339;用…

【React】React18 Hooks 之 useReducer

目錄 useReducer案例1&#xff1a;useReducer不帶初始化函數案例2&#xff1a;useReducer帶初始化函數注意事項1&#xff1a;dispatch函數不會改變正在運行的代碼的狀態注意事項2&#xff1a;獲取dispatch函數觸發后 JavaScript 變量的值注意事項3&#xff1a;觸發了reducer&am…

webrtc sfu性能壓測

1. 前言 不少網友最近私信我&#xff0c;咨詢webrtc sfu服務端性能問題&#xff0c;SRS開源服務能支持多少路webrtc流&#xff0c;mediasoup單房間能支持多少個人&#xff0c;推流能接入多少路&#xff0c;拉流能拉取多少路&#xff1f;720p能支持多少路&#xff0c;360p能支持…