国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

解析C++編程中如何使用設計模式中的狀態模式結構

2020-05-23 14:06:30
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了如何在C++編程中適用設計模式中的狀態模式結構,狀態模式強調將特定狀態相關的邏輯分散到一些類的狀態類中,需要的朋友可以參考下
 

作用:當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。

UML圖如下:

C++編程,狀態模式結構

State類,抽象狀態類,定義一個接口以封裝與Context的一個特定狀態相關的行為。
ConcreteState類,具體狀態,每一個子類實現一個與Context的一個狀態相關的行為。
Context類,維護一個ConcreteState子類的實例,這個實例定義當前的狀態。

狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過于復雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把復雜的判斷邏輯簡化。

狀態模式的好處是將與特定狀態相關的行為局部化,并且將不同狀態的行為分割開來。

將特定的狀態相關的行為都放入一個對象中,由于所有與狀態相關的代碼都存在于某個ConcreteState中,所以通過定義新的子類可以很容易地增加新的狀態和轉換。

可以消除龐大的條件分支語句。狀態模式通過把各種狀態轉移邏輯分布到State的子類之間,來減少相互間的依賴。

當一個對象的行為取決于它的狀態,并且它必須在運行時刻根據狀態改變它的行為時,就可以考慮使用狀態模式。
另外如果業務需求某項業務有多個狀態,通常都是一些枚舉常量,狀態的變化都是依靠大量的多分支判斷語句來實現,此時應該考慮將每一種業務狀態定義為一個State的子類。這樣這些對象就可以不依賴于其他對象兒獨立變化了。

實例代碼如下:

State.h#ifndef _STATE_H_

#define _STATE_H_class Context;class State{public:  virtual void Handle(Context* pContext)=0;  ~State();protected:  State();private:};class ConcreteStateA : public State{public:  ConcreteStateA();  ~ConcreteStateA();  virtual void Handle(Context* pContext);protected:private:};class ConcreteStateB : public State{public:  ConcreteStateB();  ~ConcreteStateB();  virtual void Handle(Context* pContext);protected:private:};class ConcreteStateC : public State{public:  ConcreteStateC();  ~ConcreteStateC();  virtual void Handle(Context* pContext);protected:private:};class Context{public:  Context(State* pState);  ~Context();  void Request();  void ChangeState(State* pState);protected:private:  State* _state;};#endif


State.cpp

#include "State.h"#include <iostream>using namespace std;State::State(){}State::~State(){}ConcreteStateA::ConcreteStateA(){}ConcreteStateA::~ConcreteStateA(){}//執行該狀態的行為并改變狀態void ConcreteStateA::Handle(Context* pContext){  cout << "ConcreteStateA" << endl;  pContext->ChangeState(new ConcreteStateB());}ConcreteStateB::ConcreteStateB(){}ConcreteStateB::~ConcreteStateB(){}//執行該狀態的行為并改變狀態void ConcreteStateB::Handle(Context* pContext){  cout << "ConcreteStateB" << endl;  pContext->ChangeState(new ConcreteStateC());}ConcreteStateC::ConcreteStateC(){}ConcreteStateC::~ConcreteStateC(){}//執行該狀態的行為并改變狀態void ConcreteStateC::Handle(Context* pContext){  cout << "ConcreteStateC" << endl;  pContext->ChangeState(new ConcreteStateA());}//定義_state的初始狀態Context::Context(State* pState){  this->_state = pState;}Context::~Context(){}//對請求做處理,并設置下一狀態void Context::Request(){  if(NULL != this->_state)  {    this->_state->Handle(this);  }}//改變狀態void Context::ChangeState(State* pState){  this->_state = pState;}

main.cpp
#include "State.h"

int main(){  State* pState = new ConcreteStateA();  Context* pContext = new Context(pState);  pContext->Request();  pContext->Request();  pContext->Request();  pContext->Request();  pContext->Request();  return 0;}

總結

對于狀態模式,很多情況下和策略模式看起來極為相似。實際上它們都是為了解決具體子類實現抽象接口的實現異構問題而存在的(封裝變化),但是它們的側重各不相同。而針對算法的異構問題,模板方法模式通過繼承的方式來改變一部分算法實現(原子操作在不同具體子類中可以有不同實現),策略模式則通過組合的方式來改變整個算法(可動態替換),而狀態模式則強調的是針對不同的狀態對象可以有不同的響應。因此狀態模式實際上強調的狀態的概念,并且強調對狀態轉換的邏輯封裝,即對象可能處于不同的狀態下,而各個狀態在響應了該狀態的實現后可能會動態轉到另一個狀態,而這個轉變我們不希望 Context 的參與(Context 不必維護這個轉換)。狀態機在編譯原理的 DFA/NDFA 中很常見,針對一個輸入字符和已有串,DFA/NDFA 可能會轉換到另外一個狀態。

因此對于狀態模式有以下幾個關鍵點:

1. 狀態模式會處理算法的不同,但是更加關注的是狀態的改變。并且對于狀態的轉變邏輯一般會放在 State 子類中實現。而對于不同狀態的處理則可以放在 Context 類中,State 子類保存一個指向 Context 的引用(實際上往往傳遞一個指向 Context 的指針即可,而不必在 State 子類真正保存一個引用),以調用這些實現。當然放在 State 子類中實現也無可厚非,不過為了突出重點,使用前一種方式實現更能說明問題。當然在實際開發中,完全可以不受這個制約。

2.在具體實現過程中,對狀態的改變我們會在 Context 類中實現(因為Context 才有 State 的概念),而在 State 子類中的狀態轉變邏輯實現則通過調用這個實現來達到目的。當然為了不讓這個改變狀態的接口暴露給普通客戶程序員,我們將 Context 中這個接口聲明為 private,而在將State 類聲明為 Context 的 friend 類,并且將 State 子類中狀態改變邏輯實現聲明為 Protected,不讓普通客戶程序員調用。具體請參考示例代碼部分。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 乌审旗| 广德县| 民乐县| 通渭县| 土默特右旗| 仪征市| 景泰县| 叶城县| 比如县| 精河县| 岳阳县| 龙陵县| 尖扎县| 夹江县| 左贡县| 崇明县| 休宁县| 宜黄县| 贵南县| 武城县| 门源| 安庆市| 长丰县| 安西县| 锡林郭勒盟| 沾化县| 会同县| 荔波县| 横峰县| 庆安县| 芜湖县| 抚远县| 南城县| 勃利县| 正宁县| 长宁区| 安福县| 江川县| 汉阴县| 天气| 平塘县|