Java 狀態模式 詳解

狀態模式詳解

一、狀態模式概述

狀態模式(State Pattern)是一種行為型設計模式,它允許一個對象在其內部狀態改變時改變它的行為,使對象看起來似乎修改了它的類。

核心特點

  • 狀態封裝:將每個狀態的行為封裝到獨立的類中
  • 狀態轉換:對象在不同狀態間透明切換
  • 消除條件判斷:用多態代替狀態條件判斷
  • 開閉原則:新增狀態無需修改現有代碼

二、狀態模式的結構

主要角色

  1. Context:上下文,維護當前狀態
  2. State:抽象狀態,定義狀態接口
  3. ConcreteState:具體狀態,實現特定狀態行為

三、狀態模式的實現

1. 基本實現

// 狀態接口
public interface State {void handle(Context context);
}// 具體狀態A
public class ConcreteStateA implements State {public void handle(Context context) {System.out.println("處理狀態A的行為");context.setState(new ConcreteStateB());}
}// 具體狀態B
public class ConcreteStateB implements State {public void handle(Context context) {System.out.println("處理狀態B的行為");context.setState(new ConcreteStateA());}
}// 上下文類
public class Context {private State state;public Context(State state) {this.state = state;}public void setState(State state) {this.state = state;}public void request() {state.handle(this);}
}// 使用示例
Context context = new Context(new ConcreteStateA());
context.request(); // 執行狀態A的行為,并切換到狀態B
context.request(); // 執行狀態B的行為,并切換回狀態A

2. 更復雜的實現(訂單狀態)

// 訂單狀態接口
public interface OrderState {void next(Order order);void prev(Order order);void printStatus();
}// 新建狀態
public class NewState implements OrderState {public void next(Order order) {order.setState(new PaidState());}public void prev(Order order) {System.out.println("訂單已在初始狀態");}public void printStatus() {System.out.println("訂單狀態:新建");}
}// 已支付狀態
public class PaidState implements OrderState {public void next(Order order) {order.setState(new ShippedState());}public void prev(Order order) {order.setState(new NewState());}public void printStatus() {System.out.println("訂單狀態:已支付");}
}// 訂單類(上下文)
public class Order {private OrderState state;public Order() {this.state = new NewState();}public void setState(OrderState state) {this.state = state;}public void nextState() {state.next(this);}public void previousState() {state.prev(this);}public void printStatus() {state.printStatus();}
}

四、狀態模式的應用場景

1. 電梯狀態控制

// 電梯狀態接口
public interface ElevatorState {void openDoor();void closeDoor();void run();void stop();
}// 運行狀態
public class RunningState implements ElevatorState {public void openDoor() {System.out.println("電梯運行中不能開門");}public void closeDoor() {System.out.println("電梯門已是關閉狀態");}public void run() {System.out.println("電梯已在運行");}public void stop() {System.out.println("電梯停止運行");}
}// 停止狀態
public class StoppedState implements ElevatorState {public void openDoor() {System.out.println("電梯門打開");}public void closeDoor() {System.out.println("電梯門關閉");}public void run() {System.out.println("電梯開始運行");}public void stop() {System.out.println("電梯已是停止狀態");}
}

2. 游戲角色狀態

// 游戲角色狀態
public interface CharacterState {void attack();void defend();void move();
}// 正常狀態
public class NormalState implements CharacterState {public void attack() {System.out.println("造成100%傷害");}public void defend() {System.out.println("受到100%傷害");}public void move() {System.out.println("移動速度100%");}
}// 中毒狀態
public class PoisonedState implements CharacterState {public void attack() {System.out.println("造成80%傷害");}public void defend() {System.out.println("受到120%傷害");}public void move() {System.out.println("移動速度60%");}
}

3. TCP連接狀態

// TCP狀態接口
public interface TCPState {void open();void close();void acknowledge();
}// 已建立連接狀態
public class EstablishedState implements TCPState {public void open() {System.out.println("連接已建立,無需再次打開");}public void close() {System.out.println("關閉TCP連接");}public void acknowledge() {System.out.println("發送ACK響應");}
}// 監聽狀態
public class ListenState implements TCPState {public void open() {System.out.println("建立TCP連接");}public void close() {System.out.println("未建立連接,無需關閉");}public void acknowledge() {System.out.println("未建立連接,不能發送ACK");}
}

五、狀態模式的變體

1. 狀態表驅動

public class StateMachine {private Map<State, Map<Event, State>> transitions = new HashMap<>();private State currentState;public void addTransition(State source, Event event, State target) {transitions.computeIfAbsent(source, k -> new HashMap<>()).put(event, target);}public void handleEvent(Event event) {currentState = transitions.get(currentState).get(event);}
}

2. 狀態模式與策略模式結合

public class Context {private StateStrategy state;public void setState(StateStrategy state) {this.state = state;}public void execute() {state.execute();state = state.nextState();}
}public interface StateStrategy {void execute();StateStrategy nextState();
}

六、狀態模式的優缺點

優點

  1. 單一職責:每個狀態一個類
  2. 開閉原則:易于新增狀態
  3. 簡化上下文:消除大量條件判斷
  4. 狀態轉換顯式:狀態轉換邏輯清晰

缺點

  1. 類數量多:狀態多時代碼量大
  2. 過度設計:簡單狀態機可能不適用
  3. 狀態共享:狀態間共享數據較復雜

七、最佳實踐

  1. 合理劃分狀態:避免狀態粒度過細
  2. 共享狀態對象:無狀態的狀態對象可共享
  3. 狀態轉換控制:集中或分散管理轉換邏輯
  4. 結合其他模式:如與策略模式結合
  5. 文檔化狀態圖:維護狀態轉換關系圖

八、總結

狀態模式是管理對象狀態的有效方案,特別適用于:

  • 對象行為隨狀態改變而改變
  • 需要消除大量狀態條件判斷
  • 狀態轉換邏輯復雜
  • 需要清晰的狀態管理

在實際開發中,狀態模式常見于:

  • 工作流引擎
  • 游戲角色狀態
  • 設備控制(如電梯、自動售貨機)
  • 網絡協議實現
  • 訂單生命周期管理

正確使用狀態模式可以創建清晰、可維護的狀態管理代碼,但需要注意避免過度設計簡單場景。

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

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

相關文章

Nginx 配置 HTTPS 與 WSS 完整指南

Nginx 配置 HTTPS 與 WSS 完整指南 本教程將手把手教你如何為網站配置 HTTPS 加密訪問&#xff0c;并通過反向代理實現安全的 WebSocket&#xff08;WSS&#xff09;通信。以 https://www.zhegepai.cn 域名為例&#xff0c;完整流程約需 30 分鐘完成。 一、前置準備 1.1 域名…

雙向鏈表的理解

背景 代碼中經常會出現雙向鏈表&#xff0c;對于雙向鏈表的插入和刪除有對應的API函數接口&#xff0c;但直觀的圖表更容易理解&#xff0c;所以本文會對rt-thread內核代碼中提供的雙向鏈表的一些API函數操作進行繪圖&#xff0c;方便后續隨時查看。 代碼塊 rt-thread中提供…

大文件上傳源碼,支持單個大文件與多個大文件

大文件上傳源碼&#xff0c;支持單個大文件與多個大文件 Ⅰ 思路Ⅱ 具體代碼前端--單個大文件前端--多個大文件前端接口后端 Ⅰ 思路 具體思路請參考我之前的文章&#xff0c;這里分享的是上傳流程與源碼 https://blog.csdn.net/sugerfle/article/details/130829022 Ⅱ 具體代碼…

Unity中的靜態合批使用整理

靜態批處理是一種繪制調用批處理方法&#xff0c;它組合不移動的網格以減少繪制調用。它將組合的網格轉換為世界空間&#xff0c;并為它們構建一個共享頂點和索引緩沖區。然后&#xff0c;對于可見網格&#xff0c;Unity 會執行一系列簡單的繪制調用&#xff0c;每個調用之間幾…

【機器學習中的基本術語:特征、樣本、訓練集、測試集、監督/無監督學習】

機器學習基本術語詳解 1. 特征&#xff08;Feature&#xff09; 定義&#xff1a;數據的屬性或變量&#xff0c;用于描述樣本的某個方面。作用&#xff1a;模型通過學習特征與目標之間的關系進行預測。示例&#xff1a; 預測房價時&#xff0c;特征可以是 面積、地段、房齡。…

C++學習之路:指針基礎

目錄 指針介紹與基本用法雙重指針函數指針空指針與野指針函數參數的指針傳遞最后 指針一般在C/C語言學習的后期接觸&#xff0c;這樣就導致指針給新手一種高深莫測、難以掌握的刻板印象。但實際上指針的使用很簡單&#xff0c;并且還能夠極大的提高程序的靈活性&#xff0c;幫助…

【服務日志鏈路追蹤】

MDCInheritableThreadLocal和spring cloud sleuth 在微服務架構中&#xff0c;日志鏈路追蹤&#xff08;Logback Distributed Tracing&#xff09; 是一個關鍵需求&#xff0c;主要用于跟蹤請求在不同服務間的調用鏈路&#xff0c;便于排查問題。常見的實現方案有兩種&#x…

Kafka+Zookeeper從docker部署到spring boot使用完整教程

文章目錄 一、Kafka1.Kafka核心介紹&#xff1a;?核心架構?核心特性?典型應用 2.Kafka對 ZooKeeper 的依賴&#xff1a;3.去 ZooKeeper 的演進之路&#xff1a;注&#xff1a;&#xff08;本文采用ZooKeeper3.8 Kafka2.8.1&#xff09; 二、Zookeeper1.核心架構與特性2.典型…

JUC系列JMM學習之隨筆

JUC: JUC 是 Java 并發編程的核心工具包,全稱為 Java Util Concurrent,是 java.util.concurrent 包及其子包的簡稱。它提供了一套強大且高效的并發編程工具,用于簡化多線程開發并提高性能。 CPU核心數和線程數的關系:1核處理1線程(同一時間單次) CPU內核結構: 工作內…

The Rust Programming Language 學習 (九)

泛型 每一個編程語言都有高效處理重復概念的工具。在 Rust 中其工具之一就是 泛型&#xff08;generics&#xff09;。泛型是具體類型或其他屬性的抽象替代。我們可以表達泛型的屬性&#xff0c;比如他們的行為或如何與其他泛型相關聯&#xff0c;而不需要在編寫和編譯代碼時知…

藍橋杯 混乘數字

問題描述 混乘數字的定義如下&#xff1a; 對于一個正整數 n&#xff0c;如果存在正整數 a 和 b&#xff0c;使得&#xff1a; n a b且 a 與 b 的十進制數位中每個數字出現的次數之和&#xff0c;與 n 中對應數字出現的次數相同&#xff0c;則稱 n 為混乘數字。 示例 對于…

CExercise04_1位運算符_2 定義一個函數判斷給定的正整數是否為2的冪

題目&#xff1a; 給定一個正整數&#xff0c;請定義一個函數判斷它是否為2的冪(1, 2, 4, 8, 16, …) 分析&#xff1a; &#xff1a; 代碼 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdbool.h>/* 給定一個正整數&#xff0c;請定義一個函數…

SSL證書不可信的原因有哪些?(國科云)

SSL證書用于在客戶端和服務器端之間建立一條加密通道&#xff0c;確保數據在傳輸過程中的安全性和完整性。然而&#xff0c;在實際應用中&#xff0c;我們有時會遇到SSL證書不可信的情況&#xff0c;嚴重影響了用戶對網站的信任度。那么&#xff0c;SSL證書不可信的原因究竟有哪…

[王陽明代數講義]琴語言類型系統工程特性

琴語言類型系統工程特性 層展物理學組織實務與藝術與琴生生.物機.械科.技工.業研究.所軟凝聚態物理開發工具包社會科學氣質砥礪學人生意氣場社群成員魅力場與心氣微積分社會關系力學 意氣實體過程圖論信息編碼&#xff0c;如來碼導引 注意力機制道裝Transformer架構的發展標度律…

自抗擾ADRC之二階線性擴展狀態觀測器(LESO)推導

1.龍伯格觀測器 實際工程應用中&#xff0c;狀態變量有時難以使用傳感器直接測量&#xff0c;在這種情況下&#xff0c;使用狀態觀測器估計系統實際狀態是非常常見的做法。最出名的狀態觀測器當屬龍伯格博士在1971年發表于TAC的An Introduction to Observer[1]一文中提出的基于…

從頭開發一個Flutter插件(二)高德地圖定位插件

開發基于高德定位SDK的Flutter插件 在上一篇文章里具體介紹了Flutter插件的具體開發流程&#xff0c;從創建項目到發布。接下來將為Flutter天氣項目開發一個基于高德定位SDK的Flutter定位插件。 申請key 首先進入高德地圖定位SDK文檔內下載定位SDK&#xff0c;并按要求申請A…

分布式鎖之redis6

一、分布式鎖介紹 之前我們都是使用本地鎖&#xff08;synchronize、lock等&#xff09;來避免共享資源并發操作導致數據問題&#xff0c;這種是鎖在當前進程內。 那么在集群部署下&#xff0c;對于多個節點&#xff0c;我們要使用分布式鎖來避免共享資源并發操作導致數據問題…

ubuntu中使用安卓模擬器

本文這里介紹 使用 android studio Emulator &#xff0c; 當然也有 Anbox (Lightweight)&#xff0c; Waydroid (Best for Full Android Experience), 首先確保自己安裝了 android studio &#xff1b; sudo apt update sudo apt install openjdk-11-jdk sudo snap install…

二語習得理論(Second Language Acquisition, SLA)如何學習英語

二語習得理論&#xff08;Second Language Acquisition, SLA&#xff09;是研究學習者如何在成人或青少年階段學習第二語言&#xff08;L2&#xff09;的理論框架。該理論主要關注語言習得過程中的認知、社會和文化因素&#xff0c;解釋了學習者如何從初學者逐漸變得流利并能夠…

WinDbg. From A to Z! 筆記(下)

原文鏈接: WinDbg. From A to Z! 文章目錄 使用WinDbg臨界區相關命令示例 -- 查看臨界區其他有用的命令 WinDbg中的偽寄存器自動偽寄存器 WinDbg中的表達式其他操作默認的表達式計算方式 WinDbg中的重命名調試器命令語言編程控制流命令程序執行 WinDbg 遠程調試事件監控WinDbg …