Java行為型模式---狀態模式

狀態模式基礎概念

狀態模式(State Pattern)是一種行為型設計模式,其核心思想是允許對象在內部狀態發生改變時改變它的行為,對象看起來好像修改了它的類。狀態模式將狀態相關的行為封裝在獨立的狀態類中,并將狀態轉換邏輯集中管理,從而使對象的行為可以根據狀態動態變化,而不必使用大量的條件語句。

狀態模式的核心組件

  1. 狀態接口(State)?- 定義特定狀態下的行為接口,所有具體狀態類需實現該接口。
  2. 具體狀態類(ConcreteState)?- 實現狀態接口,封裝與特定狀態相關的行為。
  3. 上下文(Context)?- 持有一個狀態對象的引用,負責狀態的切換和委托行為到當前狀態。

狀態模式的實現

下面通過一個簡單的自動販賣機示例展示狀態模式的實現:

// 1. 狀態接口
interface State {void insertCoin();  // 投幣void ejectCoin();   // 退幣void selectItem();  // 選擇商品void dispense();    // 發放商品
}// 2. 具體狀態類 - 沒有硬幣
class NoCoinState implements State {private VendingMachine machine;  // 持有上下文引用public NoCoinState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("您投入了硬幣");machine.setState(machine.getHasCoinState());  // 狀態轉換}@Overridepublic void ejectCoin() {System.out.println("您還沒有投幣");}@Overridepublic void selectItem() {System.out.println("請先投幣");}@Overridepublic void dispense() {System.out.println("請先投幣并選擇商品");}
}// 3. 具體狀態類 - 有硬幣
class HasCoinState implements State {private VendingMachine machine;public HasCoinState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("您已經投過硬幣了,無需再投");}@Overridepublic void ejectCoin() {System.out.println("硬幣已退回");machine.setState(machine.getNoCoinState());  // 狀態轉換}@Overridepublic void selectItem() {System.out.println("您選擇了商品");machine.setState(machine.getSoldState());  // 狀態轉換}@Overridepublic void dispense() {System.out.println("請先選擇商品");}
}// 4. 具體狀態類 - 已售出
class SoldState implements State {private VendingMachine machine;public SoldState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("請稍等,正在出貨");}@Overridepublic void ejectCoin() {System.out.println("抱歉,您已經選擇了商品,無法退幣");}@Overridepublic void selectItem() {System.out.println("請稍等,正在出貨");}@Overridepublic void dispense() {if (machine.getCount() > 0) {machine.releaseItem();System.out.println("商品已發放");if (machine.getCount() > 0) {machine.setState(machine.getNoCoinState());  // 還有庫存,回到無硬幣狀態} else {System.out.println("商品已售罄");machine.setState(machine.getSoldOutState());  // 庫存不足,轉為售罄狀態}} else {System.out.println("商品已售罄");machine.setState(machine.getSoldOutState());}}
}// 5. 具體狀態類 - 售罄
class SoldOutState implements State {private VendingMachine machine;public SoldOutState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("抱歉,商品已售罄");}@Overridepublic void ejectCoin() {System.out.println("您還沒有投幣");}@Overridepublic void selectItem() {System.out.println("抱歉,商品已售罄");}@Overridepublic void dispense() {System.out.println("抱歉,商品已售罄");}
}// 6. 上下文 - 自動販賣機
class VendingMachine {private State noCoinState;private State hasCoinState;private State soldState;private State soldOutState;private State state;  // 當前狀態private int count;    // 商品數量public VendingMachine(int count) {this.count = count;// 初始化狀態noCoinState = new NoCoinState(this);hasCoinState = new HasCoinState(this);soldState = new SoldState(this);soldOutState = new SoldOutState(this);// 設置初始狀態if (count > 0) {state = noCoinState;} else {state = soldOutState;}}// 狀態轉換方法public void setState(State state) {this.state = state;}// 委托行為到當前狀態public void insertCoin() {state.insertCoin();}public void ejectCoin() {state.ejectCoin();}public void selectItem() {state.selectItem();}public void dispense() {state.dispense();}// 其他方法public void releaseItem() {if (count > 0) {count--;}}public int getCount() {return count;}// 獲取各種狀態(供狀態類使用)public State getNoCoinState() {return noCoinState;}public State getHasCoinState() {return hasCoinState;}public State getSoldState() {return soldState;}public State getSoldOutState() {return soldOutState;}
}// 7. 客戶端代碼
public class StatePatternClient {public static void main(String[] args) {// 創建有2個商品的販賣機VendingMachine machine = new VendingMachine(2);// 測試流程1:投幣 -> 選擇商品 -> 出貨System.out.println("=== 測試流程1 ===");machine.insertCoin();machine.selectItem();machine.dispense();// 測試流程2:投幣 -> 退幣System.out.println("\n=== 測試流程2 ===");machine.insertCoin();machine.ejectCoin();// 測試流程3:連續購買2個商品,使販賣機售罄System.out.println("\n=== 測試流程3 ===");machine.insertCoin();machine.selectItem();machine.dispense();machine.insertCoin();machine.selectItem();machine.dispense();// 嘗試在售罄狀態下操作System.out.println("\n=== 測試售罄狀態 ===");machine.insertCoin();machine.selectItem();}
}

狀態模式的應用場景

  1. 工作流系統?- 如訂單狀態(待支付、已支付、已發貨、已完成)
  2. 游戲開發?- 角色狀態(站立、行走、跑步、跳躍、攻擊)
  3. 狀態機實現?- 如協議解析、編譯原理中的詞法分析器
  4. GUI 組件?- 如按鈕狀態(正常、懸停、點擊、禁用)
  5. 線程狀態管理?- 線程的不同狀態(新建、就緒、運行、阻塞、終止)
  6. 文檔編輯系統?- 文檔狀態(草稿、審核中、已發布、已歸檔)

狀態模式的優缺點

優點

  • 封裝狀態行為?- 將特定狀態的行為封裝在獨立的類中,提高代碼內聚性
  • 簡化條件語句?- 避免使用大量的 if-else 或 switch 語句,使代碼更清晰
  • 符合開閉原則?- 可以輕松添加新的狀態類,無需修改現有代碼
  • 狀態轉換集中管理?- 狀態轉換邏輯集中在上下文或狀態類中,便于維護
  • 狀態變化透明?- 狀態變化對客戶端透明,客戶端無需關心狀態轉換細節

缺點

  • 類數量增加?- 每個狀態都需要一個類,可能導致類爆炸
  • 狀態間依賴?- 狀態類之間可能存在依賴關系,增加系統復雜度
  • 初始化復雜?- 上下文需要初始化所有可能的狀態,增加初始化復雜度
  • 不適用于簡單狀態?- 對于狀態較少或狀態轉換簡單的場景,使用狀態模式可能過于繁瑣

使用狀態模式的注意事項

  1. 合理設計狀態接口?- 確保狀態接口包含所有可能的行為,避免狀態類中出現空實現
  2. 控制狀態數量?- 避免定義過多的狀態,狀態過多會增加系統復雜度
  3. 狀態轉換邏輯?- 決定狀態轉換邏輯放在上下文還是狀態類中:
    • 上下文控制:集中管理狀態轉換,狀態類更簡單
    • 狀態類控制:狀態類可以自主決定何時轉換,更靈活
  4. 狀態對象的生命周期?- 決定狀態對象是單例還是每次創建新實例
  5. 與策略模式的區別?- 狀態模式的狀態之間通常有關聯和轉換,而策略模式的策略之間相互獨立
  6. 調試和監控?- 狀態模式可能使調試變得復雜,建議添加狀態日志或監控機制

總結

狀態模式通過將對象的狀態相關行為封裝在獨立的狀態類中,并將狀態轉換邏輯集中管理,實現了對象行為的動態變化。它在不修改對象類的前提下,允許對象在內部狀態改變時改變其行為,是處理復雜狀態轉換場景的理想選擇。在實際開發中,狀態模式常用于工作流系統、游戲開發、狀態機實現等領域。合理使用狀態模式可以提高系統的可維護性和可擴展性,但需要注意控制類的數量和狀態轉換邏輯的復雜度。

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

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

相關文章

重學Framework Input模塊:如何實現按鍵一鍵啟動Activity-學員作業

需求背景: 近來vip群里學員朋友有問道一個需求,大概需求就是他們做TV的Framework開發,想要遙控器有一個新定義的兒童節目按鍵,想要實現這個按鍵按下后就跳轉到兒童節目的Activity。需求拆解及作業要求: 針對上面需求&a…

bmp圖像操作:bmp圖像保存及raw與bmp轉換

1. 保存bmp圖像&保存一張正弦圖像到D:\1.bmp /********************************************** * fileName bmpinc.h * brief 對bmp文件的操作,包括: * - saveBmp:保存bmp文件 * - Save…

SpringAI——提示詞(Prompt)、提示詞模板(PromptTemplate)

Prompt 是引導 AI 模型生成特定輸出的輸入格式,Prompt 的設計和措辭會顯著影響模型的響應。最開始Prompt只是單純的文本文字,后面可以包含占位符,可以識別消息的角色。比如包含占位符的Prompt,也就是我們講的消息模板(PromptTemplate)&#x…

【深度學習筆記 Ⅰ】5 參數和超參數

在深度學習中,參數(Parameters) 和 超參數(Hyperparameters) 是模型訓練中兩個核心概念,它們共同決定了模型的性能,但作用方式和優化方法截然不同。以下是詳細對比與解析:1. 參數&am…

Linux 阻塞等待框架

在 Linux 設備驅動開發中,阻塞機制 是處理資源暫時不可用(如設備未準備好數據、緩沖區滿等)的核心手段。驅動程序可以將被阻塞的進程設置成休眠狀態,然后,在資源可用后,再將該進程喚醒。 在 Linux 驅動開發…

PCIe RAS學習專題(3):AER內核處理流程梳理

目錄 一、AER內核處理整體流程梳理 二、AER代碼重要部分梳理 1、AER初始化階段 2、中斷上半部 aer_irq 3、中斷下半部 aer_isr 3.1、aer_isr_one_error 3.2、find_source_device 3.3、aer_process_err_devices 3.4、handle_error_source 3.5、pcie_do_recovery 整體邏…

?HAProxy負載均衡集群概述

前言: 在現代分布式系統中,負載均衡和高可用性是保障服務穩定性和性能的關鍵技術。HAProxy 作為一款高性能的 TCP/HTTP 負載均衡器,憑借其輕量級、高并發處理能力和靈活的配置機制,成為構建高可用架構的核心組件之一。通過智能的流…

ELN:生物醫藥科研的數字化引擎——衍因科技引領高效創新

在生物醫藥研究領域,實驗數據的準確記錄與管理是科研成敗的關鍵。想象一個場景:某頂尖醫學院實驗室,研究員小張正為一項抗癌藥物實驗焦頭爛額。紙質記錄本中,數據混亂、協作困難,導致實驗重復率高達20%。引入衍因科技的…

暑假---作業2

學習目標&#xff1a;xss-1abs 1-8關python美現自動化布爾自注的2、代碼進行優化(二分查找)學習內容&#xff1a;1.xss-1abs 1-8關1<h2 align"center">歡迎用戶test</h2>2 <script> alert (1)</script&gt<center> <form action&…

【Tensor數據轉換】——深度學習.Torch框架

目錄 1 Tensor與Numpy 1.1 張量轉Numpy 1.2 Numpy轉張量 1 Tensor與Numpy 1.1 張量轉Numpy 調用numpy()方法可以把Tensor轉換為Numpy&#xff0c;此時內存是共享的。 使用copy()方法可以避免內存共享 import torch import numpy as np# tensor轉numpy:numpy() def test0…

基于Tranformer的NLP實戰(5):BERT實戰-基于Pytorch Lightning的文本分類模型

文本分類作為自然語言處理中的基礎任務&#xff0c;能夠幫助我們將海量醫學摘要自動歸類到具體疾病領域中。本文將基于NVIDIA NeMo框架&#xff0c;構建一個用于醫學疾病摘要分類的深度學習應用&#xff0c;支持將摘要劃分為三類&#xff1a;癌癥類疾病、神經系統疾病及障礙、以…

14-鏈路聚合

鏈路聚合技術 一 鏈路聚合概述鏈路聚合定義鏈路聚合是把多條物理鏈路聚合在一起&#xff0c;形成一條邏輯鏈路。應用在交換機、路由器、服務器間鏈路。分為三層鏈路聚合和二層鏈路聚合。二 鏈路聚合的作用 1. 鏈路聚合模式靜態聚合模式 端口不與對端設備交互信息。選擇參考端口…

學習C++、QT---28(QT庫中使用QShortcut類對快捷鍵創建和使用的講解)

每日一言 所有的努力&#xff0c;都是為了讓未來的自己感謝現在的你。 QShortcut 我們的記事本肯定要有通過快捷鍵對字體的放大和縮小進行控制的功能啊&#xff0c;那么我們這邊就這個問題我們需要先學習一下QShortCut 我們這個類就是專門做快捷鍵的 老樣子我們剛開始學習這個…

Web Worker:讓前端飛起來的隱形引擎

目錄 Web Worker&#xff1a;讓前端飛起來的隱形引擎 一、什么是 Web Worker&#xff1f; 1、為什么需要 web worker 2、什么是 web worker 二、基本使用方法 1、創建一個 Worker 文件&#xff08;worker.js&#xff09; 2、主線程引入并使用 三、實戰案例&#xff1a;…

關于在VScode中使用git的一些步驟常用命令及其常見問題:

輸入 gitee用戶 gitee綁定郵箱git config --global user.name "automated-piggy-senior" git config --global user.email "1323280131qq.com"克隆遠程庫到本地 git clone https://gitee.com/automated-piggy-senior/20250717-test.git常見問題1&#xff1…

LeafletJS 性能優化:處理大數據量地圖

引言 LeafletJS 作為一個輕量、靈活的 JavaScript 地圖庫&#xff0c;以其高效的渲染能力和模塊化設計深受開發者喜愛。然而&#xff0c;當處理大數據量&#xff08;如數千個標記、復雜的 GeoJSON 數據或高分辨率瓦片&#xff09;時&#xff0c;LeafletJS 的性能可能面臨挑戰&…

LLM(Large Language Model)大規模語言模型淺析

參考: https://zhuanlan.zhihu.com/p/7046080918 LLM(Large Language Model)大規模語言模型,是指具有大規模參數和復雜計算結構的機器學習模型。大模型里常說的多少B, B 是 Billion 的縮寫&#xff0c;表示 十億,如DeepSeek滿血版 671B(6710億參數); 大模型本質上是一個使用海量…

【后端】配置SqlSugar ORM框架并添加倉儲

目錄 1.添加包 2.配置連接字符串 3.配置SqlSugar 3.1.添加基礎類 3.2.添加方法 3.2.1.讀取配置方法 3.2.2.枚舉擴展方法 3.3.添加管理類&#xff08;重要&#xff09; 4.配置倉儲 4.1.倉儲接口添加 5.注冊 6.使用 該文檔是配置SqlSugar多租戶和加倉儲教程。使用 S…

全國高等院校計算機基礎教育研究會2025學術年會在西寧成功舉辦 ——高原論道啟新程,數智融合育英才

7 月16日至18日&#xff0c;全國高等院校計算機基礎教育研究會2025學術年會在青海西寧隆重召開。大會以“數智融合&#xff0c;創新計算機教育”為主題&#xff0c;匯聚人工智能領域頂尖專家學者、高校校長、產業翹楚及一線教師300 多人&#xff0c;共商人工智能時代計算機基礎…

AppTrace:重新定義免填邀請碼,解鎖用戶裂變新高度

??在移動互聯網時代&#xff0c;?用戶裂變是App增長的核心引擎&#xff0c;而邀請機制則是裂變的關鍵驅動力。然而&#xff0c;傳統的邀請碼機制——依賴用戶手動輸入、記憶復雜字符——已經成為用戶體驗的絆腳石&#xff0c;導致轉化率下降、運營成本上升。?AppTrace? 作…