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

來源:互聯網
上載者:User

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

UML圖如下:

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,不讓普通客戶程式員調用。具體請參考範例程式碼部分。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.