最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解state狀態(tài)模式及在C++設(shè)計(jì)模式編程中的使用實(shí)例

 更新時(shí)間:2016年03月09日 17:41:16   作者:夢在天涯  
這篇文章主要介紹了state狀態(tài)模式及在C++設(shè)計(jì)模式編程中的使用實(shí)例,在設(shè)計(jì)模式中策略用來處理算法變化,而狀態(tài)則是透明地處理狀態(tài)變化,需要的朋友可以參考下

每個(gè)人、事物在不同的狀態(tài)下會有不同表現(xiàn)(動作),而一個(gè)狀態(tài)又會在不同的表現(xiàn)下轉(zhuǎn)移到下一個(gè)不同的狀態(tài)(State)。最簡單的一個(gè)生活中的例子就是:地鐵入口處,如果你放入正確的地鐵票,門就會打開讓你通過。在出口處也是驗(yàn)票,如果正確你就可以 ok,否則就不讓你通過(如果你動作野蠻,或許會有報(bào)警(Alarm),:))。

有限狀態(tài)自動機(jī)(FSM)也是一個(gè)典型的狀態(tài)不同,對輸入有不同的響應(yīng)(狀態(tài)轉(zhuǎn)移)。

通常我們在實(shí)現(xiàn)這類系統(tǒng)會使用到很多的 Switch/Case 語句,Case 某種狀態(tài),發(fā)生什么動作,Case 另外一種狀態(tài),則發(fā)生另外一種狀態(tài)。但是這種實(shí)現(xiàn)方式至少有以下兩個(gè)問題:
當(dāng)狀態(tài)數(shù)目不是很多的時(shí)候,Switch/Case 可能可以搞定。但是當(dāng)狀態(tài)數(shù)目很多的時(shí)候(實(shí)際系統(tǒng)中也正是如此),維護(hù)一大組的 Switch/Case 語句將是一件異常困難并且容易出錯(cuò)的事情。
狀態(tài)邏輯和動作實(shí)現(xiàn)沒有分離。在很多的系統(tǒng)實(shí)現(xiàn)中,動作的實(shí)現(xiàn)代碼直接寫在狀態(tài)的邏輯當(dāng)中。這帶來的后果就是系統(tǒng)的擴(kuò)展性和維護(hù)得不到保證。

狀態(tài)模式就是被用來解決上面列出的兩個(gè)問題的,在狀態(tài)模式中我們將狀態(tài)邏輯和動作實(shí)現(xiàn)進(jìn)行分離。當(dāng)一個(gè)操作中要維護(hù)大量的 case 分支語句,并且這些分支依賴于對象的狀態(tài)。狀態(tài)模式將每一個(gè)分支都封裝到獨(dú)立的類中。

狀態(tài)模式典型的結(jié)構(gòu)圖為:

201639173716593.jpg (558×259)

狀態(tài)模式的實(shí)現(xiàn)
代碼片斷 1:State.h

//state.h
#ifndef _STATE_H_
#define _STATE_H_
class Context; //前置聲明
class State{
  public:
  State();
  virtual ~State();
  virtual void OperationInterface(Context* ) = 0;
  virtual void OperationChangeState(Context*) = 0;
  protected:
  bool ChangeState(Context* con,State* st);
  private:
  //bool ChangeState(Context* con,State* st);
};
class ConcreteStateA:public State{
  public:
  ConcreteStateA();
  virtual ~ConcreteStateA();
  virtual void OperationInterface(Context* );
  virtual void OperationChangeState(Context*);
  protected:
  private:
};
class ConcreteStateB:public State{
  public:
  ConcreteStateB();
  virtual ~ConcreteStateB();
  virtual void OperationInterface(Context* );
  virtual void OperationChangeState(Context*);
  protected:
  private:
};
#endif //~_STATE_H_

代碼片斷 2:State.cpp

//State.cpp
#include "State.h"
#include "Context.h"
#include <iostream>
using namespace std;
State::State(){
}
State::~State(){
}
void State::OperationInterface(Context* con){
  cout<<"State::.."<<endl;
}
bool State::ChangeState(Context* con,State* st){
  con->ChangeState(st);
  return true;
}
void State::OperationChangeState(Context* con){
}
///
ConcreteStateA::ConcreteStateA(){
}
ConcreteStateA::~ConcreteStateA(){
}
void ConcreteStateA::OperationInterface(Context* con){
  cout<<"ConcreteStateA::OperationInterface
  ......"<<endl;
}
void ConcreteStateA::OperationChangeState(Context* con){
  OperationInterface(con);
  this->ChangeState(con,new ConcreteStateB());
}
///
ConcreteStateB::ConcreteStateB(){
}
ConcreteStateB::~ConcreteStateB(){
}
void ConcreteStateB::OperationInterface(Context* con){
  cout<<"ConcreteStateB::OperationInterface......"<<endl;
}
void ConcreteStateB::OperationChangeState(Context* con){
  OperationInterface(con);
  this->ChangeState(con,new ConcreteStateA());
}

代碼片斷 3:Context.h

//context.h
#ifndef _CONTEXT_H_
#define _CONTEXT_H_
class State;
/**
*
**/
class Context{
  public:
  Context();
  Context(State* state);
  ~Context();
  void OprationInterface();
  void OperationChangState();
  protected:
  private:
  friend class State; //表明在 State 類中可以訪問 Context 類的 private 字段
  bool ChangeState(State* state);
  private:
  State* _state;
};
#endif //~_CONTEXT_H_

代碼片斷 4:Context.cpp

//context.cpp
#include "Context.h"
#include "State.h"
Context::Context(){
}
Context::Context(State* state){
  this->_state = state;
}
Context::~Context(){
  delete _state;
}
void Context::OprationInterface(){
  _state->OperationInterface(this);
}
bool Context::ChangeState(State* state){
  ///_state->ChangeState(this,state);
  this->_state = state;
  return true;
}
void Context::OperationChangState(){
  _state->OperationChangeState(this);
}

代碼片斷 5:main.cpp

//main.cpp
#include "Context.h"
#include "State.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[]){
  State* st = new ConcreteStateA();
  Context* con = new Context(st);
  con->OperationChangState();
  con->OperationChangState();
  con->OperationChangState();
  if (con != NULL)
    delete con;
  if (st != NULL)
    st = NULL;
  return 0;
}

代碼說明:狀態(tài)模式在實(shí)現(xiàn)中,有兩個(gè)關(guān)鍵點(diǎn):
1.將狀態(tài)聲明為 Context 的友元類(friend class),其作用是讓狀態(tài)模式訪問 Context的 protected 接口 ChangeSate()。
狀態(tài)及其子類中的操作都將 Context*傳入作為參數(shù),其主要目的是狀態(tài)類可以通過這個(gè)指針調(diào)用 Context 中的方法(在本示例代碼中沒有體現(xiàn))。這也是狀態(tài)模式和 Strategy模式的最大區(qū)別所在。

2.運(yùn)行了示例代碼后可以獲得以下的結(jié)果:連續(xù) 3 次調(diào)用了 Context 的 OprationInterface()因?yàn)槊看握{(diào)用后狀態(tài)都會改變(A-B-A),因此該動作隨著 Context 的狀態(tài)的轉(zhuǎn)變而獲得了不同的結(jié)果。


關(guān)于State模式的一些需要注意的地方
這個(gè)模式使得軟件可以在不同的state下面呈現(xiàn)出完全不同的特征

不同的theme使得相同的元素呈現(xiàn)出不同的特點(diǎn)
不同的state下面相同的操作產(chǎn)生不同的效果
不同的狀態(tài)對相同的信息產(chǎn)生不同的處理
這個(gè)模式使得操作的state邏輯更加的清楚,省去了無數(shù)的state判斷,而state的擴(kuò)展性和可維護(hù)性和執(zhí)行效率也大幅度的上升。關(guān)于state,有如下幾點(diǎn)要注意的地方:

1.所有的state應(yīng)該被一個(gè)類(State Manager Class)管理:

state之間的跳轉(zhuǎn)和轉(zhuǎn)換是非常復(fù)雜的,有時(shí)一些state可能要跳轉(zhuǎn)的目標(biāo)state有幾十個(gè),這個(gè)時(shí)候我們需要一個(gè)管理類(State Manager )來統(tǒng)一的管理這些state的切換,例如目標(biāo)state的初始化和申請?zhí)D(zhuǎn)state的結(jié)束處理,以及一些state間共享數(shù)據(jù)的存儲和處理。與其稱這個(gè)Manager 為管理類,不如說是一個(gè)中間類,它實(shí)現(xiàn)了state之間的解隅,使得各個(gè)state之間不比知道target state的具體信息,而只要向Manager申請?zhí)D(zhuǎn)就可以了。使得各個(gè)state的模塊化更好,更加的靈活

2.所有的state都應(yīng)該從一個(gè)state基類繼承:

既然state要教給一個(gè)manager來管理,那么自然的,這些state都應(yīng)該從一個(gè)父類繼承下來,這樣manager并不需要知道很多子類的信息,一個(gè)最單純的manager只要只要管理一個(gè)這樣的基類的指針就可以了。另外,我們還可以統(tǒng)一的把state的一些共有的屬性放在這里

3.state應(yīng)該實(shí)現(xiàn)為一個(gè)singleton:

state并不需要總是被申請,這樣可能會造成管理上的混亂,state資源的申請也不應(yīng)該可以任意進(jìn)行,事實(shí)上,state的申請權(quán)限應(yīng)該只有 Manager才有,并且有且只有一次。在這樣的情況下,state的構(gòu)造函數(shù)似乎應(yīng)該被聲明為protected or private ,而Manager應(yīng)該被聲明為state的友元,但是友元被看成是破壞類的封裝性的一種做法,這一點(diǎn)上,我很矛盾,所以在這一條上我只能采取一種漠視的態(tài)度。

4.應(yīng)該做一個(gè)state么?這是一個(gè)問題:

state可以說是if-else的一種替代品,極端的情況下面state可以讓你的程序中if-else程序塊消失得無影無蹤,但是,這并不是銀彈。state對于狀態(tài)可預(yù)知的情況下非常有效,但是對于state不可預(yù)知,或者相似的state數(shù)量太多。過多的state會造成class的粒度過細(xì),程序反而不簡潔。在這樣的情況下,你應(yīng)該考慮使用if-else程序塊來替代state。

例如:

有這樣的一個(gè)程序,它可以生成任意形狀的多邊形,而多邊形的各個(gè)節(jié)點(diǎn)是可以移動的,問題就來了。

我并不知道用戶將要使用多少個(gè)節(jié)點(diǎn)的多邊形,因此我無法的創(chuàng)建那么多相應(yīng)的state來使得這樣一個(gè)程序正常工作。state大多數(shù)都是確定的,對于不確定的,state似乎無能為力,例如此例

一種解決方法是我利用Manager傳遞給state一個(gè)state參數(shù),讓state有機(jī)會知道用戶的操作意圖,在這個(gè)例子里面是讓state知道用戶打算操作某一個(gè)節(jié)點(diǎn),而state根據(jù)這個(gè)state參數(shù)來處理用戶的操作,比如說,state得到的是用戶操作的某一個(gè)點(diǎn)的index ,而state只要寫

points[index].moveTo(points[index].getX()+offset_x , points[index].getY()+offset_y);

就可以,從而避免了state過多出現(xiàn)的問題。

相關(guān)文章

  • C語言實(shí)現(xiàn)掃雷經(jīng)典游戲

    C語言實(shí)現(xiàn)掃雷經(jīng)典游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)掃雷經(jīng)典游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++實(shí)現(xiàn)高并發(fā)異步定時(shí)器

    C++實(shí)現(xiàn)高并發(fā)異步定時(shí)器

    這篇文章主要為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)高并發(fā)異步定時(shí)器,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • 詳解進(jìn)程同步與互斥機(jī)制

    詳解進(jìn)程同步與互斥機(jī)制

    進(jìn)程同步是一個(gè)操作系統(tǒng)級別的概念,是在多道程序的環(huán)境下,存在著不同的制約關(guān)系,為了協(xié)調(diào)這種互相制約的關(guān)系,實(shí)現(xiàn)資源共享和進(jìn)程協(xié)作,從而避免進(jìn)程之間的沖突,引入了進(jìn)程同步
    2021-06-06
  • C++動態(tài)規(guī)劃計(jì)算最大子數(shù)組

    C++動態(tài)規(guī)劃計(jì)算最大子數(shù)組

    所謂最大子數(shù)組就是連續(xù)的若干數(shù)組元素,如果其和是最大的,那么這個(gè)子數(shù)組就稱為該數(shù)組的最大子數(shù)組
    2022-06-06
  • c++ string的erase刪除方法

    c++ string的erase刪除方法

    這篇文章主要介紹了c++ string的erase刪除方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • C++空類默認(rèn)函數(shù)詳細(xì)解析

    C++空類默認(rèn)函數(shù)詳細(xì)解析

    如果你只是聲明一個(gè)空類,不做任何事情的話,編譯器會自動為你生成一個(gè)默認(rèn)構(gòu)造函數(shù)、一個(gè)拷貝默認(rèn)構(gòu)造函數(shù)、一個(gè)默認(rèn)拷貝賦值操作符和一個(gè)默認(rèn)析構(gòu)函數(shù)
    2013-10-10
  • C語言switch語句詳解

    C語言switch語句詳解

    這篇文章主要為大家介紹了C語言switch語句,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C語言中函數(shù)聲明與調(diào)用問題

    C語言中函數(shù)聲明與調(diào)用問題

    以下是對C語言中的函數(shù)聲明與調(diào)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下
    2013-08-08
  • 深入了解c語言的循環(huán)語句

    深入了解c語言的循環(huán)語句

    這篇文章主要為大家介紹了c語言的循環(huán)語句,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C++版本基于ros將文件夾中的圖像轉(zhuǎn)換為bag包

    C++版本基于ros將文件夾中的圖像轉(zhuǎn)換為bag包

    這篇文章主要介紹了C++版本基于ros將文件夾中的圖像轉(zhuǎn)換為bag包,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01

最新評論

林芝县| 申扎县| 冀州市| 五指山市| 云阳县| 奇台县| 项城市| 乌鲁木齐市| 深水埗区| 旌德县| 宜宾市| 老河口市| 南郑县| 西安市| 临夏县| 都安| 五寨县| 海城市| 准格尔旗| 绥化市| 五原县| 临洮县| 遂平县| 海宁市| 巴彦淖尔市| 元氏县| 灵寿县| 綦江县| 子长县| 珠海市| 聊城市| 宝坻区| 金塔县| 清丰县| 瓦房店市| 滨州市| 扎囊县| 龙海市| 通化市| 衡东县| 上林县|