C++ 狀態模式詳解

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

核心概念

設計原則

狀態模式遵循以下設計原則:

  1. 單一職責原則:將狀態相關行為分離到不同類中

  2. 開閉原則:可以新增狀態而不修改現有代碼

  3. 封裝性:狀態轉換邏輯封裝在狀態類中

主要優點

  1. 清晰狀態轉換:將狀態轉換邏輯組織化

  2. 減少條件語句:消除龐大的條件狀態判斷

  3. 可擴展性:容易添加新狀態和轉換

  4. 行為局部化:狀態特定行為集中在對應狀態類中

模式結構

主要組件

  1. Context(上下文)

    • 維護當前狀態的引用

    • 將狀態相關請求委托給當前狀態對象

  2. State(狀態接口)

    • 定義狀態接口

    • 封裝與Context特定狀態相關的行為

  3. ConcreteState(具體狀態)

    • 實現狀態接口

    • 每個子類實現與Context狀態相關的行為

完整代碼示例

#include <iostream>
#include <memory>
#include <string>// 前置聲明
class State;// ==================== 上下文類 ====================
class Player {std::unique_ptr<State> state_;std::string name_;public:explicit Player(const std::string& name);void setState(std::unique_ptr<State> state);std::string getName() const;// 玩家行為void play();void pause();void stop();void lock();void unlock();
};// ==================== 狀態接口 ====================
class State {
public:virtual ~State() = default;virtual void play(Player* player) = 0;virtual void pause(Player* player) = 0;virtual void stop(Player* player) = 0;virtual void lock(Player* player) = 0;virtual void unlock(Player* player) = 0;protected:void changeState(Player* player, std::unique_ptr<State> state) {player->setState(std::move(state));}
};// ==================== 具體狀態 ====================
class ReadyState : public State {
public:void play(Player* player) override;void pause(Player* player) override { /* 無效操作 */ }void stop(Player* player) override { /* 無效操作 */ }void lock(Player* player) override;void unlock(Player* player) override { /* 已在解鎖狀態 */ }
};class PlayingState : public State {
public:void play(Player* player) override { /* 已在播放狀態 */ }void pause(Player* player) override;void stop(Player* player) override;void lock(Player* player) override;void unlock(Player* player) override { /* 無效操作 */ }
};class PausedState : public State {
public:void play(Player* player) override;void pause(Player* player) override { /* 已在暫停狀態 */ }void stop(Player* player) override;void lock(Player* player) override;void unlock(Player* player) override { /* 無效操作 */ }
};class LockedState : public State {
public:void play(Player* player) override { /* 鎖定狀態下不能播放 */ }void pause(Player* player) override { /* 鎖定狀態下不能暫停 */ }void stop(Player* player) override { /* 鎖定狀態下不能停止 */ }void lock(Player* player) override { /* 已在鎖定狀態 */ }void unlock(Player* player) override;
};// ==================== 上下文方法實現 ====================
Player::Player(const std::string& name) : name_(name) {state_ = std::make_unique<ReadyState>();
}void Player::setState(std::unique_ptr<State> state) {state_ = std::move(state);
}std::string Player::getName() const {return name_;
}void Player::play() {state_->play(this);
}void Player::pause() {state_->pause(this);
}void Player::stop() {state_->stop(this);
}void Player::lock() {state_->lock(this);
}void Player::unlock() {state_->unlock(this);
}// ==================== 具體狀態方法實現 ====================
void ReadyState::play(Player* player) {std::cout << player->getName() << ": 開始播放" << std::endl;changeState(player, std::make_unique<PlayingState>());
}void ReadyState::lock(Player* player) {std::cout << player->getName() << ": 鎖定播放器" << std::endl;changeState(player, std::make_unique<LockedState>());
}void PlayingState::pause(Player* player) {std::cout << player->getName() << ": 暫停播放" << std::endl;changeState(player, std::make_unique<PausedState>());
}void PlayingState::stop(Player* player) {std::cout << player->getName() << ": 停止播放" << std::endl;changeState(player, std::make_unique<ReadyState>());
}void PlayingState::lock(Player* player) {std::cout << player->getName() << ": 鎖定播放器" << std::endl;changeState(player, std::make_unique<LockedState>());
}void PausedState::play(Player* player) {std::cout << player->getName() << ": 恢復播放" << std::endl;changeState(player, std::make_unique<PlayingState>());
}void PausedState::stop(Player* player) {std::cout << player->getName() << ": 停止播放" << std::endl;changeState(player, std::make_unique<ReadyState>());
}void PausedState::lock(Player* player) {std::cout << player->getName() << ": 鎖定播放器" << std::endl;changeState(player, std::make_unique<LockedState>());
}void LockedState::unlock(Player* player) {std::cout << player->getName() << ": 解鎖播放器" << std::endl;changeState(player, std::make_unique<ReadyState>());
}// ==================== 客戶端代碼 ====================
int main() {std::cout << "=== 狀態模式演示: 音樂播放器 ===" << std::endl;Player player("我的播放器");// 正常流程player.play();player.pause();player.play();player.stop();// 鎖定測試std::cout << "\n測試鎖定功能:" << std::endl;player.play();player.lock();player.play();  // 應該無效player.unlock();player.play();// 無效操作測試std::cout << "\n測試無效操作:" << std::endl;player.stop();player.stop();  // 應該無效player.pause(); // 應該無效return 0;
}

模式變體

1. 狀態表驅動

class StateMachine {std::unordered_map<std::string, std::unordered_map<std::string, std::function<void()>>> transitions_;std::string currentState_;public:void addTransition(const std::string& from, const std::string& event, const std::string& to, std::function<void()> action) {transitions_[from][event] = [this, to, action] {action();currentState_ = to;};}void handleEvent(const std::string& event) {auto& stateTransitions = transitions_[currentState_];if (stateTransitions.find(event) != stateTransitions.end()) {stateTransitions[event]();}}
};

2. 共享狀態對象

class SharedState : public State {// 可以共享的狀態數據
};class ConcreteStateA : public SharedState {// 實現特定行為
};// 使用時可以共享同一個狀態實例
auto sharedState = std::make_shared<ConcreteStateA>();
context1.setState(sharedState);
context2.setState(sharedState);

實際應用場景

  1. 工作流引擎:如訂單狀態流轉

  2. 游戲開發:角色行為狀態管理

  3. UI系統:控件不同狀態下的行為

  4. 網絡協議:協議狀態機實現

  5. 硬件控制:設備狀態管理

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

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

相關文章

Html5新特性_js 給元素自定義屬性_json 詳解_淺克隆與深克隆

文章目錄 1. html5新特性2.用 js 給元素自定義屬性3.json3.1 json與普通對象的區別3.2 json對象與 js對象的轉化 4.淺克隆和深克隆 1. html5新特性 html5中引入了新的特性&#xff08;新的標簽&#xff09;&#xff0c;下面的新標簽是新的結構標簽&#xff0c;不過不太常用 h…

std::move 和 std::forward

關聯點 都是執行轉換(cast)的函數&#xff08;函數模板&#xff09;&#xff0c;不產生任何可執行代碼。且都可以把實參轉換成右值。 std::move無條件將實參&#xff08;const除外 &#xff09;轉換成右值引用&#xff0c;std::forward 條件返回右值引用 _EXPORT_STD template…

Uniapp編寫微信小程序,使用canvas進行繪圖

一、canvas文檔&#xff1a; https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial 二、數據繪制&#xff08;單位是像素&#xff09;&#xff1a; 1、繪制文本&#xff1a; 文字的長度超過設置的最大寬度&#xff0c;文字會縮在一起 ① 填充文本&#xf…

FLASH閃存(擦除、編譯)

FLASH閃存 文章目錄 FLASH閃存1.存儲器映像位置2.FLASH簡介3.閃存模塊組織3.2閃存的共性&#xff1a; 4.FLASH基本結構4.1FLASH解鎖4.2使用指針訪問寄存器 5.選項字節5.1選項字節編程5.2選項字節擦除 6.相關函數介紹7.讀取內部FLASH&#xff08;實操&#xff09;7.1接線圖7.2工…

PostgreSQL 序列(Sequence) 與 Oracle 序列對比

PostgreSQL 序列(Sequence) 與 Oracle 序列對比 PostgreSQL 和 Oracle 都提供了序列(Sequence)功能&#xff0c;但在實現細節和使用方式上存在一些重要差異。以下是兩者的詳細對比&#xff1a; 一 基本語法對比 1.1 創建序列 PostgreSQL: CREATE [ { TEMPORARY | TEMP } |…

12.2.2 allocator類

allocator類將分配內存空間、調用構造函數、調用析構函數、釋放內存空間這4部分操作分開&#xff0c;全部交給程序員來執行&#xff0c;不像new和delete #include <iostream> #include <string>int main() {const int n 10;std::allocator<std::string> al…

Android 中 Handler (創建時)內存泄漏問題及解決方案

一、Handler 內存泄漏核心原理 真題 1&#xff1a;分析 Handler 內存泄漏場景 題目描述&#xff1a; 在 Activity 中使用非靜態內部類 Handler 發送延遲消息&#xff0c;旋轉屏幕后 Activity 無法釋放&#xff0c;分析原因并給出解決方案。 內存泄漏鏈路分析&#xff1a; 引…

SSTI記錄

SSTI(Server-Side Template Injection&#xff0c;服務器段模板注入) 當前使用的一些框架&#xff0c;如python的flask、php的tp、java的spring&#xff0c;都采用成熟的MVC模式&#xff0c;用戶的輸入會先進入到Controller控制器&#xff0c;然后根據請求的類型和請求的指令發…

探索邊緣計算:賦能物聯網的未來

摘要 隨著物聯網&#xff08;IoT&#xff09;技術的飛速發展&#xff0c;越來越多的設備接入網絡&#xff0c;產生了海量的數據。傳統的云計算模式在處理這些數據時面臨著延遲高、帶寬不足等問題&#xff0c;而邊緣計算的出現為解決這些問題提供了新的思路。本文將深入探討邊緣…

tabs切換#

1、html <el-tabs v-model"tabValue" tab-change"handleTabClick"><el-tab-pane label"集群" name"1"></el-tab-pane><el-tab-pane label"節點" name"2"></el-tab-pane></el-ta…

JSON 實體屬性映射的最佳實踐

一、結構與命名規范 ?保持字段命名一致性? JSON 字段名與實體屬性名應遵循統一的命名規則&#xff08;如駝峰命名或下劃線分隔&#xff09;&#xff0c;避免因大小寫差異導致映射失敗。 // 使用 JsonProperty 顯式指定映射關系&#xff08;Jackson&#xff09; public class …

hiveserver2與beeline進行遠程連接hive配置及遇到的問題

1、hiveserver2 參與用戶模擬功能&#xff0c;因為開啟后才能保證各用戶之間的權限隔離。 1.1、配置 $HADOOP_HOME/etc/hadoop/core-site.xml <!--配置所有節點的root用戶都可作為代理用戶--> <property><name>hadoop.proxyuser.root.hosts</name>&…

硅基計劃2.0 學習總結 壹 Java初階

一、初見Java &#xff08;1&#xff09;Java簡介 首先不得不承認Java是一門優秀的程序設計語言 其系列的計算機軟件和跨平臺體系包括國內的生態鏈完善是C/C語言難以彌補的 &#xff08;2&#xff09;Java SE 全稱Java Standard Edition&#xff0c;是Java體系的基礎 &am…

nRF5_SDK_17.1.0_ddde560之ble_app_uart_c 出錯

Error #541: ARM::CMSIS:CORE:5.3.0 component is missing (previously found in pack ARM.CMSIS.5.6.0) Error #541: NordicSemiconductor::Device:Startup:8.40.3 component is missing (previously found in pack NordicSemiconductor.nRF_DeviceFamilyPack.8.40.3) 下載n…

基于大模型預測的多發性硬化綜合診療方案研究報告大綱

目錄 一、引言二、文獻綜述三、大模型預測系統構建四、術前預測與手術方案制定五、術中監測與決策支持六、術后護理與并發癥預測七、麻醉方案智能優化八、統計分析與技術驗證九、實驗驗證與證據支持十、健康教育與指導系統十一、結論與展望一、引言 (一)研究背景與意義 多發…

bootstrap自助(抽樣)法

一&#xff0c;概念 一言以蔽之&#xff1a;從訓練集中有放回的均勻抽樣——》本質就是有放回抽樣&#xff1b; 自助法&#xff08;bootstrap&#xff09;是一種通過從數據集中重復抽樣來估計統計量分布的非參數方法。它可用于構建假設檢驗&#xff0c;當對參數模型的假設存在…

用1W字講透數據預處理,數據增強

大家好&#xff01;我是我不是小upper~ 今天咱們來聊聊數據增強 —— 這個在機器學習領域堪稱 “數據魔法” 的實用技術&#xff01; 在深度學習的世界里&#xff0c;數據就像模型的 “養分”。數據的質量和數量&#xff0c;直接決定了模型最終能達到的 “高度”。當數據不足時…

無人機空中物流優化:用 Python 打造高效配送模型

友友們好! 我是Echo_Wish,我的的新專欄《Python進階》以及《Python!實戰!》正式啟動啦!這是專為那些渴望提升Python技能的朋友們量身打造的專欄,無論你是已經有一定基礎的開發者,還是希望深入挖掘Python潛力的愛好者,這里都將是你不可錯過的寶藏。 在這個專欄中,你將會…

C++核心編程解析:模板、容器與異常處理全指南

文章目錄 一、模板1.1 定義1.2 作用1.3 函數模版1.3.1 格式 1.4 類模版1.4.1 格式1.4.2 代碼示例1.4.3 特性 二、容器2.1 概念2.2 容器特性2.3 分類2.4 向量vector2.4.1 特性2.4.2 初始化與操作2.4.3 插入刪除 2.5 迭代器2.6 列表&#xff08;list&#xff09;2.6.1 遍歷方式2.…

JWT的介紹與在Fastapi框架中的應用

什么是JWT JWT (JSON Web Token) 是一個開放標準 ( RFC 7519 )&#xff0c;它定義了一種緊湊且自包含的方式&#xff0c;用于在各方之間安全地以 JSON 對象的形式傳輸信息。由于這些信息經過數字簽名&#xff0c;因此可以被驗證和信任。JWT 可以使用密鑰&#xff08;采用HMAC算…