程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 詳解state狀況形式及在C++設計形式編程中的應用實例

詳解state狀況形式及在C++設計形式編程中的應用實例

編輯:關於C++

詳解state狀況形式及在C++設計形式編程中的應用實例。本站提示廣大學習愛好者:(詳解state狀況形式及在C++設計形式編程中的應用實例)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解state狀況形式及在C++設計形式編程中的應用實例正文


每一個人、事物在分歧的狀況下會有分歧表示(舉措),而一個狀況又會在分歧的表示下轉移到下一個分歧的狀況(State)。最簡略的一個生涯中的例子就是:地鐵進口處,假如你放入准確的地鐵票,門就會翻開讓你經由過程。在出口處也是驗票,假如准確你便可以 ok,不然就不讓你經由過程(假如你舉措蠻橫,也許會有報警(Alarm),:))。

無限狀況主動機(FSM)也是一個典范的狀況分歧,對輸出有分歧的呼應(狀況轉移)。

平日我們在完成這類體系會應用到許多的 Switch/Case 語句,Case 某種狀況,產生甚麼舉措,Case 別的一種狀況,則產生別的一種狀況。然則這類完成方法至多有以下兩個成績:
當狀況數量不是許多的時刻,Switch/Case 能夠可以弄定。然則當狀況數量許多的時刻(現實體系中也恰是如斯),保護一年夜組的 Switch/Case 語句將是一件異常艱苦而且輕易失足的工作。
狀況邏輯和舉措完成沒有分別。在許多的體系完成中,舉措的完成代碼直接寫在狀況的邏輯傍邊。這帶來的效果就是體系的擴大性和保護得不到包管。

狀況形式就是被用來處理下面列出的兩個成績的,在狀況形式中我們將狀況邏輯和舉措完成停止分別。當一個操作中要保護年夜量的 case 分支語句,而且這些分支依附於對象的狀況。狀況形式將每個分支都封裝到自力的類中。

狀況形式典范的構造圖為:

狀況形式的完成
代碼片段 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;
}

代碼解釋:狀況形式在完成中,有兩個症結點:
1.將狀況聲明為 Context 的友元類(friend class),其感化是讓狀況形式拜訪 Context的 protected 接口 ChangeSate()。
狀況及其子類中的操作都將 Context*傳入作為參數,其重要目標是狀況類可以經由過程這個指針挪用 Context 中的辦法(在本示例代碼中沒有表現)。這也是狀況形式和 Strategy形式的最年夜差別地點。

2.運轉了示例代碼後可以取得以下的成果:持續 3 次挪用了 Context 的 OprationInterface()由於每次挪用後狀況都邑轉變(A-B-A),是以該舉措跟著 Context 的狀況的改變而取得了分歧的成果。


關於State形式的一些須要留意的處所
這個形式使得軟件可以在分歧的state上面出現出完整分歧的特點

分歧的theme使得雷同的元素出現出分歧的特色
分歧的state上面雷同的操作發生分歧的後果
分歧的狀況對雷同的信息發生分歧的處置
這個形式使得操作的state邏輯加倍的清晰,省去了有數的state斷定,而state的擴大性和可保護性和履行效力也年夜幅度的上升。關於state,有以下幾點要留意的處所:

1.一切的state應當被一個類(State Manager Class)治理:

state之間的跳轉和轉換長短常龐雜的,有時一些state能夠要跳轉的目的state有幾十個,這個時刻我們須要一個治理類(State Manager )來同一的治理這些state的切換,例如目的state的初始化和請求跳轉state的停止處置,和一些state間同享數據的存儲和處置。與其稱這個Manager 為治理類,不如說是一個中央類,它完成了state之間的解隅,使得各個state之間不比曉得target state的詳細信息,而只需向Manager請求跳轉便可以了。使得各個state的模塊化更好,加倍的靈巧

2.一切的state都應當從一個state基類繼續:

既然state要教給一個manager來治理,那末天然的,這些state都應當從一個父類繼續上去,如許manager其實不須要曉得許多子類的信息,一個最純真的manager只需只需治理一個如許的基類的指針便可以了。別的,我們還可以同一的把state的一些共有的屬性放在這裡

3.state應當完成為一個singleton:

state其實不須要老是被請求,如許能夠會形成治理上的凌亂,state資本的請求也不該該可以隨意率性停止,現實上,state的請求權限應當只要 Manager才有,而且有且只要一次。在如許的情形下,state的結構函數仿佛應當被聲明為protected or private ,而Manager應當被聲明為state的友元,然則友元被算作是損壞類的封裝性的一種做法,這一點上,我很抵觸,所以在這一條上我只能采用一種疏忽的立場。

4.應當做一個state麼?這是一個成績:

state可以說是if-else的一種替換品,極真個情形上面state可讓你的法式中if-else法式塊消逝得無影無蹤,然則,這其實不是銀彈。state關於狀況可預知的情形下異常有用,然則關於state弗成預知,或許類似的state數目太多。過量的state會形成class的粒渡過細,法式反而不簡練。在如許的情形下,你應當斟酌應用if-else法式塊來替換state。

例如:

有如許的一個法式,它可以生成隨意率性外形的多邊形,而多邊形的各個節點是可以挪動的,成績就來了。

我其實不曉得用戶將要應用若干個節點的多邊形,是以我沒法的創立那末多響應的state來使得如許一個法式正常任務。state年夜多半都是肯定的,關於不肯定的,state仿佛力所不及,例如斯例

一種處理辦法是我應用Manager傳遞給state一個state參數,讓state無機會曉得用戶的操作意圖,在這個例子外面是讓state曉得用戶盤算操作某一個節點,而state依據這個state參數來處置用戶的操作,好比說,state獲得的是用戶操作的某一個點的index ,而state只需寫

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

便可以,從而防止了state過量湧現的成績。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved