C++如何處理對象的狀態變化?

概念

處理對象的狀態變化是軟件開發中一個重要的課題,尤其是在設計過程中,如何有效管理對象的狀態變化對于軟件的可維護性、可擴展性和整體設計都至關重要。

狀態模式

狀態模式通過將狀態封裝為對象,允許對象在內部狀態改變時改變其行為。狀態模式使得狀態的切換變得靈活,減少了條件語句的使用。

#include <iostream>  
#include <memory>  // 前向聲明  
class Context;  // 抽象狀態類  
class State {  
public:  virtual void handle(Context& context) = 0;  virtual ~State() = default;  
};  // 上下文類  
class Context {  
private:  std::unique_ptr<State> state;  public:  Context(std::unique_ptr<State> initialState) : state(std::move(initialState)) {}  void setState(std::unique_ptr<State> newState) {  state = std::move(newState);  }  void request() {  state->handle(*this); // 使用當前狀態進行處理  }  
};  // 具體狀態類 A  
class ConcreteStateA : public State {  
public:  void handle(Context& context) override {  std::cout << "Handling state A. Transitioning to state B." << std::endl;  context.setState(std::make_unique<ConcreteStateB>()); // 轉換狀態  }  
};  // 具體狀態類 B  
class ConcreteStateB : public State {  
public:  void handle(Context& context) override {  std::cout << "Handling state B. Transitioning to state A." << std::endl;  context.setState(std::make_unique<ConcreteStateA>()); // 轉換狀態  }  
};  int main() {  Context context(std::make_unique<ConcreteStateA>());  context.request(); // 當前是狀態 A  context.request(); // 當前是狀態 B  context.request(); // 當前是狀態 A  context.request(); // 當前是狀態 B  return 0;  
}

代碼解析

  • 狀態基類:定義了處理方法的接口,子類需要實現具體行為。
  • 具體狀態類:分別實現不同狀態的行為,并在處理過程中改變上下文的狀態。
  • 上下文類:持有一個狀態對象,通過調用當前狀態的 handle 方法來響應請求,并允許狀態的轉換。

觀察者模式

觀察者模式用于建立一種一對多的依賴關系,當被觀察者的狀態改變時,所有依賴于它的觀察者都會收到通知。適用于需要通知多個對象狀態變化的場景。

#include <iostream>  
#include <vector>  
#include <memory>  // 抽象觀察者類  
class Observer {  
public:  virtual void update() = 0;  virtual ~Observer() = default;  
};  // 抽象被觀察者類  
class Subject {  
public:  virtual void attach(std::shared_ptr<Observer> observer) = 0;  virtual void detach(std::shared_ptr<Observer> observer) = 0;  virtual void notify() = 0;  virtual ~Subject() = default;  
};  // 具體被觀察者  
class ConcreteSubject : public Subject {  
private:  std::vector<std::shared_ptr<Observer>> observers;  int state;  public:  void setState(int newState) {  state = newState;  notify();  }  int getState() const {  return state;  }  void attach(std::shared_ptr<Observer> observer) override {  observers.push_back(observer);  }  void detach(std::shared_ptr<Observer> observer) override {  // 在這里可以實現 detach 邏輯  }  void notify() override {  for (const auto& observer : observers) {  observer->update(); // 通知所有觀察者  }  }  
};  // 具體觀察者  
class ConcreteObserver : public Observer {  
private:  ConcreteSubject& subject;  public:  ConcreteObserver(ConcreteSubject& subject) : subject(subject) {}  void update() override {  std::cout << "Observer updated: New state = " << subject.getState() << std::endl;  }  
};  int main() {  ConcreteSubject subject;  auto observer1 = std::make_shared<ConcreteObserver>(subject);  subject.attach(observer1); // 注冊觀察者  subject.setState(1); // 改變狀態,通知觀察者  subject.setState(2); // 再改變狀態,通知觀察者  return 0;  
}

代碼解析

  • 觀察者接口:定義了一個更新方法,所有具體觀察者都需實現該方法。
  • 被觀察者接口:定義附加、解除和通知觀察者的方法。
  • 具體被觀察者:持有觀察者的列表,維護自己的狀態,并在狀態變化時通知觀察者。
  • 具體觀察者:在狀態變化時采取相應的行動。

狀態機模式

狀態機模式通常用于表示有限狀態機的行為,適用于狀態變化明確且數量有限的場景。狀態機可以維護狀態轉移的規則和條件。

#include <iostream>  
#include <map>  
#include <functional>  // 狀態機類  
class StateMachine {  
public:  using State = std::string;  using Transition = std::function<void()>;  private:  State currentState;  std::map<State, std::map<State, Transition>> transitions;  public:  void addTransition(State from, State to, Transition transition) {  transitions[from][to] = transition; // 記錄狀態轉移  }  void setState(State state) {  currentState = state; // 設置當前狀態  }  void transition(State to) {  if (transitions[currentState].count(to)) {  transitions[currentState][to](); // 執行轉移邏輯  currentState = to; // 更新當前狀態  } else {  std::cout << "Invalid transition from " << currentState << " to " << to << std::endl;  }  }  State getCurrentState() const {  return currentState; // 獲取當前狀態  }  
};  int main() {  StateMachine sm;  // 添加狀態轉移  sm.addTransition("Idle", "Working", []() {  std::cout << "Transitioning from Idle to Working." << std::endl;  });  sm.addTransition("Working", "Idle", []() {  std::cout << "Transitioning from Working to Idle." << std::endl;  });  sm.setState("Idle");  sm.transition("Working"); // 有效轉移  sm.transition("Idle");    // 有效轉移  sm.transition("Working");  // 有效轉移  sm.transition("Idle");     // 有效轉移  return 0;  
}

代碼解析

  • 狀態機類:管理當前狀態和狀態轉移邏輯。
  • 狀態轉移:通過方法 transition 來執行狀態之間的切換,檢查是否允許轉移,并執行轉移后的邏輯。

使用監聽器模式

在某些情況下,可以通過事件的方式來處理狀態變化,使用事件監聽器來觀察和處理狀態變化。

#include <iostream>  
#include <vector>  
#include <string>  // 監聽器接口  
class Listener {  
public:  virtual void onStateChanged(const std::string& newState) = 0;  virtual ~Listener() = default;  
};  // 主類,它的狀態會變化  
class StateTracker {  
private:  std::string state;  std::vector<Listener*> listeners;  public:  void addListener(Listener* listener) {  listeners.push_back(listener);  }  void changeState(const std::string& newState) {  state = newState;  notifyListeners();  }  void notifyListeners() {  for (auto listener : listeners) {  listener->onStateChanged(state); // 通知所有監聽者  }  }  
};  // 具體監聽者  
class ConcreteListener : public Listener {  
public:  void onStateChanged(const std::string& newState) override {  std::cout << "State changed to: " << newState << std::endl;  }  
};  int main() {  StateTracker tracker;  ConcreteListener listener;  tracker.addListener(&listener); // 添加監聽者  tracker.changeState("Active");   // 改變狀態,觸發通知  tracker.changeState("Inactive"); // 再改變狀態,觸發通知  return 0;  
}

代碼解析

  • 監聽器接口:定義了狀態變化的響應方法。
  • 主類:持有狀態并維護監聽者列表,狀態變化時通知所有監聽者。
  • 具體監聽者:實現狀態變化時的處理邏輯。

總結

處理對象的狀態變化通常可以通過幾種設計模式和技術來實現,選擇適當的方法取決于項目需求和復雜性。這些方法包括:

  • 狀態模式:將不同狀態封裝為對象,負責相應的行為。
  • 觀察者模式:允許多個觀察者監視狀態的變化,并在狀態變化時得到通知。
  • 狀態機模式:清晰地管理狀態和狀態之間的轉移邏輯。
  • 監聽器模式:以事件驅動的方式處理狀態變化。

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

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

相關文章

在Spring中application 的配置屬性(詳細)

application 的配置屬性。 這些屬性是否生效取決于對應的組件是否聲明為 Spring 應用程序上下文里的 Bean &#xff08;基本是自動配置 的&#xff09;&#xff0c;為一個不生效的組件設置屬性是沒有用的。 multipart multipart.enabled 開啟上傳支持&#xff08;默認&a…

C語言編程1.27漢諾塔

題目描述 給定一個由n個圓盤組成的塔&#xff0c;這些圓盤按照大小遞減的方式套在第一根樁柱上。現要將整個塔移動到另一根樁柱上&#xff0c;每次只能移動一個圓盤&#xff0c;且較大的圓盤在移動過程中不能放置在較小的圓盤上面。 輸入格式 輸入由四行&#xff1a; 第一行…

初學stm32 --- 時鐘配置

目錄 stm32時鐘系統 時鐘源 &#xff08;1&#xff09; 2 個外部時鐘源&#xff1a; &#xff08;2&#xff09;2 個內部時鐘源&#xff1a; 鎖相環 PLL PLLXTPRE&#xff1a; HSE 分頻器作為 PLL 輸入 (HSE divider for PLL entry) PLLSRC&#xff1a; PLL 輸入時鐘源 (PL…

【Java基礎面試題025】什么是Java的Integer緩存池?

回答重點 Java的Integer緩存池&#xff08;Integer Cache&#xff09;是為了提升性能和節省內存。根據實踐發現大部分的數據操作都集中在值比較小的范圍&#xff0c;因此緩存這些對象可以減少內存分配和垃圾回收的負擔&#xff0c;提升性能 在 -128到127范圍內的Integer對象會…

Nginx IP優化限制策略

Nginx 如何限制每個 IP 地址的連接數&#xff0c;優化資源分配&#xff1f; Nginx 限制每個 IP 地址的連接數 Nginx 提供了多種機制來限制單個 IP 地址所能建立的同時連接數&#xff0c;這對于防止資源耗盡和提高服務穩定性至關重要。以下是幾種有效策略&#xff1a; 1. 使用…

[spring]XML配置文件標簽

spring的XML配置文件的標簽大體可以分為兩種&#xff1a; 其中的默認標簽&#xff0c;我們前面文章里面出現的標簽都是默認標簽&#xff0c;是spring本身自帶的&#xff0c;不需要我們去引入其他東西。而自定義標簽則是指非默認標簽的其他的由我們或產品發行方自定義的對接spir…

簡單的bytebuddy學習筆記

簡單的bytebuddy學習筆記 此筆記對應b站bytebuddy學習視頻進行整理&#xff0c;此為視頻地址&#xff0c;此處為具體的練習代碼地址 一、簡介 ByteBuddy是基于ASM (ow2.io)實現的字節碼操作類庫。比起ASM&#xff0c;ByteBuddy的API更加簡單易用。開發者無需了解class file …

【信息系統項目管理師】高分論文:論信息系統項目的進度管理(人力資源管理系統)

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 論文1、規劃進度管理3、排列活動順序4、估算活動持續時間5、制訂進度計劃6、控制進度論文 2022年2月,我作為項目經理參與了XX電網公司人力資源管理系統建設項目,該項目是2022年XX電網公司“十三五”信息化規…

vue3項目結合Echarts實現甘特圖(可拖拽、選中等操作)

效果圖&#xff1a; 圖一&#xff1a;選中操作 圖二&#xff1a;上下左右拖拽操作 本案例在echarts???????示例機場航班甘特圖的基礎上修改??????? 封裝ganttEcharts組件&#xff0c;測試數據 airport-schedule.jsonganttEcharts代碼: 直接復制粘貼可測????…

GIT安裝過程

文章目錄 ?下載安裝包?安裝過程?驗證安裝?Git的基本使用? ?Git的安裝可以通過以下步驟完成? ?下載安裝包? 首先&#xff0c;訪問Git官網(https://git-scm.com/)或Git for Windows(https://gitforwindows.org/)下載對應系統的安裝包。 對于Windows系統&#xff0c;通常…

Java 技術面試常見問題解析

1.說說Mybatis的緩存機制: MyBatis 是一個優秀的持久層框架&#xff0c;它簡化了企業應用開發中數據庫操作的代碼。MyBatis 提供了一級緩存和二級緩存機制來優化對數據庫的訪問。 一級緩存 (SqlSession級別的緩存) 一級緩存是 MyBatis 中默認開啟且無法關閉的緩存機制。它存…

Word使用分隔符實現頁面部分分欄

文章目錄 Word使用分隔符實現頁面部分分欄分隔符使用頁面設置 Word使用分隔符實現頁面部分分欄 分隔符使用 word中的分隔符&#xff1a; 前面不分欄&#xff0c;后面分欄(或前面分欄&#xff0c;后面不分欄)&#xff0c;只需要在分隔位置處插入分隔符&#xff1a;“連續”即…

掌握 Spring Boot 中的 WebClient:何時以及為何使用它而不是 RestTemplate

在開發 Spring Boot 應用程序時&#xff0c;與 RESTful Web 服務進行通信是一項常見需求。從歷史上看&#xff0c;開發人員已將RestTemplate用于此目的。然而&#xff0c;隨著反應式編程的出現和對更高效資源利用的需求&#xff0c;WebClient已成為首選。本文探討了RestTemplat…

主曲率為常數時曲面分類

主曲率為常數 ? K , H \Leftrightarrow K,H ?K,H 為常數&#xff0c;曲面分類&#xff1a; 1.若 k 1 k 2 0 k_1k_20 k1?k2?0,則 S S S為全臍點曲面——平面的一部分&#xff1b; 2.若 k 1 k 2 ≠ 0 k_1k_2\neq0 k1?k2?0,則 S S S為全臍點曲面——球面的一部分&…

asp.net core發布配置端口號,支持linux

方式一&#xff0c;修改配置文件 appsettings.json 找到文件 appsettings.json&#xff0c; 添加如下節點配置&#xff0c;在linux環境需要設置0.0.0.0才可以正常代表本機&#xff0c;然后被其他機器訪問&#xff0c;此處設置端口8000&#xff0c; "Kestrel": {&quo…

【安當產品應用案例100集】033-安當TDE透明加密在移動存儲加密中的應用案例

背景介紹 隨著移動互聯網的普及&#xff0c;企業和個人越來越依賴移動存儲設備&#xff0c;如U盤、移動硬盤以及云存儲服務進行數據的存儲和傳輸。然而&#xff0c;這種便捷性也帶來了數據安全的隱患。如何確保存儲在移動設備上的數據不被非法訪問和泄露&#xff0c;成為企業和…

【linux 內存】cat /proc/meminfo、free

cat /proc/meminfo 各字段詳解 /proc/meminfo是了解Linux系統內存使用狀況的主要接口&#xff0c;我們最常用的”free”、”vmstat”等命令就是通過它獲取數據的 &#xff0c;/proc/meminfo所包含的信息比”free”等命令要豐富得多&#xff0c;因此需要了解這些字段的含義。 …

Android HandlerThread、Looper、MessageQueue 源碼分析

Android HandlerThread、Looper、MessageQueue 源碼分析 簡介 在 Android 開發中&#xff0c;大家應該對 HandlerThread 有一定了解。顧名思義&#xff0c;HandlerThread 是 Thread 的一個子類。與普通的 Thread 不同&#xff0c;Thread 通常一次只能執行一個后臺任務&#x…

配置PostgreSQL用于集成測試的步驟

在進行軟件開發時&#xff0c;集成測試是確保各個組件能夠協同工作的關鍵環節。PostgreSQL作為一種強大的開源數據庫系統&#xff0c;常被用于集成測試中。下面將詳細介紹如何在不同的環境中配置PostgreSQL以支持集成測試。 1. 選擇并安裝PostgreSQL 首先&#xff0c;你需要根…

WebRTC搭建與應用(一)-ICE服務搭建

WebRTC搭建與應用(一) 近期由于項目需要在研究前端WebGL渲染轉為云渲染&#xff0c;借此機會對WebRTC、ICE信令協議等有了初步了解&#xff0c;在此記錄一下&#xff0c;以防遺忘。 第一章 ICE服務搭建 文章目錄 WebRTC搭建與應用(一)前言一、ICE是什么&#xff1f;二、什么…