設計模式之狀態模式:優雅管理對象行為變化

引言

狀態模式(State Pattern)是一種行為型設計模式,它允許對象在其內部狀態改變時改變它的行為,使對象看起來似乎修改了它的類。狀態模式將狀態轉移邏輯和狀態相關行為封裝在獨立的狀態類中,完美解決了復雜條件判斷問題。本文將深入解析狀態模式的核心思想、實現方式及典型應用場景。


1. 狀態模式的核心概念

1.1 什么是狀態模式?

狀態模式通過以下三個角色管理狀態轉換:

  • Context(上下文):維護當前狀態實例

  • State(抽象狀態):定義狀態接口

  • ConcreteState(具體狀態):實現特定狀態行為

1.2 典型應用場景
  • 訂單狀態流轉(待支付、已發貨、已完成等)

  • 游戲角色狀態(站立、奔跑、跳躍等)

  • 工作流引擎

  • UI控件狀態管理(禁用/啟用、活躍/非活躍)


2. 狀態模式的實現方式

2.1 基礎實現模板
// 狀態接口
interface State {void handle(Context context);
}// 具體狀態A
class ConcreteStateA implements State {@Overridepublic void handle(Context context) {System.out.println("處理狀態A的行為");context.setState(new ConcreteStateB()); // 狀態轉移}
}// 具體狀態B
class ConcreteStateB implements State {@Overridepublic void handle(Context context) {System.out.println("處理狀態B的行為");context.setState(new ConcreteStateA()); // 狀態轉移}
}// 上下文
class Context {private State currentState;public Context(State initialState) {this.currentState = initialState;}public void setState(State state) {this.currentState = state;}public void request() {currentState.handle(this); // 委托給當前狀態}
}// 使用示例
public class Client {public static void main(String[] args) {Context context = new Context(new ConcreteStateA());context.request(); // 輸出A行為,切換到Bcontext.request(); // 輸出B行為,切換回A}
}
2.2 進階實現技巧
  1. 狀態共享:無內部狀態的具體狀態可設計為單例

  2. 狀態創建管理:使用工廠方法管理狀態實例

  3. 狀態轉移表:用Map維護狀態轉移規則


3. 狀態模式的最佳實踐

3.1 與策略模式的區別
  • 狀態模式:狀態間知曉彼此,自動觸發狀態轉移

  • 策略模式:策略相互獨立,由客戶端指定策略

3.2 性能優化
  • 狀態對象復用:對無狀態的狀態對象使用享元模式

  • 延遲初始化:按需創建狀態對象

3.3 設計原則
  • 開閉原則:新增狀態無需修改現有代碼

  • 單一職責:每個狀態類只關注特定狀態行為


4. 狀態模式的實際應用

4.1 電商訂單系統
// 訂單狀態接口
interface OrderState {void confirm(OrderContext context);void cancel(OrderContext context);void ship(OrderContext context);
}// 具體狀態:待支付
class UnpaidState implements OrderState {@Overridepublic void confirm(OrderContext context) {System.out.println("訂單支付成功");context.setState(new PaidState());}@Overridepublic void cancel(OrderContext context) {System.out.println("訂單已取消");context.setState(new CancelledState());}@Overridepublic void ship(OrderContext context) {System.out.println("訂單未支付不能發貨");}
}// 上下文類
class OrderContext {private OrderState currentState;public OrderContext() {this.currentState = new UnpaidState(); // 初始狀態}// 委托方法...
}// 使用示例
OrderContext order = new OrderContext();
order.confirm(); // 支付成功,狀態轉為PaidState
4.2 交通信號燈系統
// 狀態接口
interface TrafficLightState {void change(TrafficLight light);String getColor();
}// 具體狀態
class RedLight implements TrafficLightState {@Overridepublic void change(TrafficLight light) {light.setState(new GreenLight());}@Overridepublic String getColor() {return "紅色";}
}// 上下文類
class TrafficLight {private TrafficLightState state;public void change() {state.change(this);}public void show() {System.out.println("當前信號燈:" + state.getColor());}
}
4.3 播放器狀態控制
// 播放器狀態接口
interface PlayerState {void play(MediaPlayer player);void pause(MediaPlayer player);void stop(MediaPlayer player);
}// 具體狀態:播放中
class PlayingState implements PlayerState {@Overridepublic void play(MediaPlayer player) {System.out.println("已在播放狀態");}@Overridepublic void pause(MediaPlayer player) {System.out.println("暫停播放");player.setState(new PausedState());}@Overridepublic void stop(MediaPlayer player) {System.out.println("停止播放");player.setState(new StoppedState());}
}// 上下文類
class MediaPlayer {private PlayerState state;public void play() {state.play(this);}public void changeState(PlayerState newState) {this.state = newState;}
}

5. 狀態模式的優缺點分析

5.1 優勢
  • 消除條件分支:用多態代替復雜的狀態判斷

  • 易于擴展:新增狀態只需添加新類

  • 集中狀態邏輯:每個狀態的行為局部化

5.2 局限性
  • 類數量增加:每個狀態對應一個類

  • 狀態轉換不直觀:轉移邏輯分散在各狀態類中

  • 不適合簡單狀態機:簡單場景可能過度設計


結語

狀態模式是管理復雜狀態轉換的利器,特別適合行為隨狀態改變而顯著變化的場景。通過將每種狀態封裝為獨立類,代碼變得清晰可維護。在實際應用中,可以結合備忘錄模式實現狀態歷史記錄,或與觀察者模式實現狀態變更通知,構建更強大的系統架構。

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

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

相關文章

【算法】歸并排序

算法系列七:歸并排序 一、歸并排序的遞歸探尋 1.思路 2.搭建 2.1設計過掉不符情況(在最底層時) 2.2查驗能實現基礎排序(在最底層往上點時) 2.3跳轉結果繼續往上回搭 3.實質 4.實現 二、遞歸的調用棧 1.遞歸的…

線束線纜從二維設計到虛擬驗證全流程解決方案

一、傳統設計中的痛點 線纜的開發設計是橫跨多專業多學科的龐大工程,通常會劃分為幾大階段逐次推進,由于每個階段的工作任務不同,所以在不同設計階段使用的工具也完全不同,由此導致整個設計流程中工程師常常要跨平臺協作&#xf…

【智駕中的大模型 -1】自動駕駛場景中的大模型

1. 前言 我們知道,大模型現在很火爆,尤其是 deepseek 風靡全球后,大模型毫無疑問成為為中國新質生產力的代表。百度創始人李彥宏也說:“2025 年可能會成為 AI 智能體爆發的元年”。 隨著科技的飛速發展,大模型的影響…

個人博客系統后端 - 注冊登錄功能實現指南

一、功能概述 個人博客系統的注冊登錄功能包括: 用戶注冊:新用戶可以通過提供用戶名、密碼、郵箱等信息創建賬號用戶登錄:已注冊用戶可以通過用戶名和密碼進行身份驗證,獲取JWT令牌身份驗證:使用JWT令牌訪問需要認證…

投行交易與風控系統的消費側冪等架構設計與實戰

1.背景和痛點 1.1 資金操作敏感性場景 核心需求: 交易唯一性:資金類操作必須保證全局唯一執行計算原子性:風控指標計算需具備事務性特征審計追溯:所有操作需保留完整冪等軌跡 1.2 業務損失統計 二、技術挑戰與架構設計 2.1 分…

odoo-046 視圖顯示的 name 數據庫中存儲的不一樣

文章目錄 一、問題由來二、排查經過1. 問 deepseek2. 驗證3. 新問題 三、 總結四、補充(翻譯模型 ir.translation 中 src 和 value 字段詳解) 一、問題由來 客戶有多個公司,使用多個數據庫。他們有時需要同步不同數據庫之間的數據的需求。在…

充電寶項目:規則引擎Drools學習

文章目錄 規則引擎 Drools1 問題2 規則引擎概述2.1 規則引擎2.2 使用規則引擎的優勢2.3 規則引擎應用場景2.4 Drools介紹 3 Drools入門案例3.1 創建springboot項目 引入依賴3.2 添加Drools配置類3.4 創建實體類Order3.5 orderScore.drl3.6 編寫測試類 4 Drools基礎語法4.1 規則…

HTML、CSS 和 JavaScript 常見用法及使用規范

一、HTML 深度剖析 1. 文檔類型聲明 HTML 文檔開頭的 <!DOCTYPE html> 聲明告知瀏覽器當前文檔使用的是 HTML5 標準。它是文檔的重要元信息&#xff0c;能確保瀏覽器以標準模式渲染頁面&#xff0c;避免怪異模式下的兼容性問題。 2. 元數據標簽 <meta> 標簽&am…

基于CNN+ViT的蔬果圖像分類實驗

本文只是做一個簡單融合的實驗&#xff0c;沒有任何新穎&#xff0c;大家看看就行了。 1.數據集 本文所采用的數據集為Fruit-360 果蔬圖像數據集&#xff0c;該數據集由 Horea Mure?an 等人整理并發布于 GitHub&#xff08;項目地址&#xff1a;Horea94/Fruit-Images-Datase…

Ubuntu24.04安裝libgl1-mesa-glx 報錯,軟件包缺失

在 Ubuntu 24.04 系統中&#xff0c;您遇到的 libgl1-mesa-glx 軟件包缺失問題可能是由于該包在最新的 Ubuntu 版本中被重命名為 libglx-mesa0。以下是針對該問題的詳細解決方案&#xff1a; 1. 問題原因分析 包名稱變更&#xff1a;在 Ubuntu 24.04 中&#xff0c;libgl1-me…

webpack vite

? 1、webpack webpack打包工具&#xff08;重點在于配置和使用&#xff0c;原理并不高優。只在開發環境應用&#xff0c;不在線上環境運行&#xff09;&#xff0c;壓縮整合代碼&#xff0c;讓網頁加載更快。 前端代碼為什么要進行構建和打包&#xff1f; 體積更好&#x…

如何在爬蟲中合理使用海外代理?在爬蟲中合理使用海外ip

我們都知道&#xff0c;爬蟲工作就是在各類網頁中游走&#xff0c;快速而高效地采集數據。然而如果目標網站分布在多個國家或者存在區域性限制&#xff0c;那靠普通的網絡訪問可能會帶來諸多阻礙。而這時&#xff0c;“海外代理”儼然成了爬蟲工程師們的得力幫手&#xff01; …

數據倉庫分層存儲設計:平衡存儲成本與查詢效率

數據倉庫分層存儲不僅是一個技術問題,更是一種藝術:如何在有限的資源下,讓數據既能快速響應查詢,又能以最低的成本存儲? 目錄 一、什么是數據倉庫分層存儲? 二、分層存儲的體系架構 1. 數據源層(ODS,Operational Data Store) 2. 數據倉庫層(DW,Data Warehouse)…

YOLO學習筆記 | 基于YOLOv8的植物病害檢測系統

以下是基于YOLOv8的植物病害檢測系統完整技術文檔,包含原理分析、數學公式推導及代碼實現框架。 基于YOLOv8的智能植物病害檢測系統研究 摘要 針對傳統植物病害檢測方法存在的效率低、泛化性差等問題,本研究提出一種基于改進YOLOv8算法的智能檢測系統。通過設計輕量化特征提…

高級語言調用C接口(二)回調函數(4)Python

前面2篇分別說了java和c#調用C接口&#xff0c;參數為回調函數&#xff0c;回調函數中參數是結構體指針。 接下來說下python的調用方法。 from ctypes import * import sysclass stPayResult(Structure):_pack_ 4 # 根據實際C結構體的對齊方式設置&#xff08;常見值為1,4,…

springboot啟動動態定時任務

1.自定義定時任務線程池 package com.x.devicetcpserver.global.tcp.tcpscheduler;import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotatio…

pytorch框架認識--手寫數字識別

手寫數字是機器學習中非常經典的案例&#xff0c;本文將通過pytorch框架&#xff0c;利用神經網絡來實現手寫數字識別 pytorch中提供了手寫數字的數據集&#xff0c;我們可以直接從pytorch中下載 MNIST中包含70000張手寫數字圖像&#xff1a;60000張用于訓練&#xff0c;10000…

WPF 使用依賴注入后關閉窗口程序不結束

原因是在ViewModel中在構造函數中注入了Window 對象&#xff0c;即使沒有使用&#xff0c;主窗口關閉程序不會退出&#xff0c;即使 ViewModel 是 AddTransient 注入的。 解決方法&#xff1a;不使用構造函數注入Window&#xff0c;通過GetService獲取Window 通過注入對象調用…

用戶管理(添加和刪除,查詢信息,切換用戶,查看登錄用戶,用戶組,配置文件)

目錄 添加和刪除用戶 查詢用戶信息 切換用戶 查看當前的操作用戶是誰 查看首次登錄的用戶是誰 用戶組&#xff08;對屬于同個角色的用戶統一管理&#xff09; 新增組 刪除組 添加用戶的同時&#xff0c;指定組 修改用戶的組 組的配置文件&#xff08;/etc/group&…

PyTorch學習-小土堆教程

網絡搭建torch.nn.Module 卷積操作 torch.nn.functional.conv2d(input, weight, biasNone, stride1, padding0, dilation1, groups1) 神經網絡-卷積層