1. 设计原理:
  • 起点是“状态”设计模式。模式的本质是用类表示状态。通过实例化这些类的对象来执行状态转换。
  • 从这个角度来看,状态类的构造函数和析构函数可以看作是进入和退出动作的角色。然后,对象属性构成状态变量。通过在状态对象上调用方法来调度事件,这些对象实现状态的保护,操作和状态转换。
  • 为了使状态组成层次结构,子状态必须能够接管超级状态的事件处理逻辑,并在必要时有选择地重新定义它。 C ++中存在一种机制,允许在方法级别上重新定义行为:通过类继承实现多态。
  • 但是,使用类继承对子状态/超状态关系进行建模是有问题的:不再可以将构造函数和析构函数用作入口和出口动作,也不能将状态变量保留在对象中。
  • 原因是基类是派生类的组成部分,这意味着对象的构造或破坏将触发所有涉及的类构造函数或析构函数,并初始化或破坏所有数据成员。
  • 这与进入/退出动作和状态变量的语义背道而驰,后者在同级子状态之间的转换不应触发超状态进入/退出动作,也不应破坏超状态状态变量。
  • 我们对这个问题的解决方案是对状态进入和退出使用显式方法,在状态转换时以正确的顺序调用它们。状态变量保存在单独的特定于状态的数据结构中,这些数据结构的生命周期与状态的层次结构一致。

  1. 注意事项:
    2.1 entry() exit()不能跳转状态;
    2.2 跳转状态只能调到单方向,不能同时调到两个方向
    2.3 状态进入:父状态—>子状态—>子状态
    2.4 状态跳出:子状态—>父状态—>父状态
    2.5 兄弟状态跳转:a entry—> a exit—> b entry---->b exit

  1. 参考使用模板:StateMachine

  1. 学习示例:
#ifndef SIMU_H
#define SIMU_H

#include <iostream>

using namespace std;

namespace SIMUSTATEMACHINE {

// state transtation : state instance and destory

class baseState;

class objHoldSate
{
public:
    explicit objHoldSate(baseState *bS);
    ~objHoldSate();

    void setState(int state);
    void getState() {
        cout << "get null temp" << endl;
    }

public:
    baseState * getStatePoint() {
        return mState;
    }
    baseState * getCurrStatePoint() {
        return curState;
    }

private:
    baseState * mState;
    baseState * curState;
};

/*
class subObjHoldState : public objHoldSate {

};
*/

class subState1;
class subState2;

class baseState
{
public:
    // entry
    /*
    baseState(objHoldSate *obj):mObj(obj) {
        mObj->mState = this;
    }
    */
    explicit baseState(int type) {
	cout << "base state entry2!" << endl;
	}
    baseState() {
	// cout << "base state entry1!" << endl;
	}
    // exit
    ~baseState();
    // start
    void start();
    // event handle
    virtual void event1() {
        cout << "dispatch event1." << endl;
    }
    virtual void event2() {
        cout << "dispatch event2" << endl;
    }
    virtual void event3() {
        cout << "dispatch event3" << endl;
    }
public:
    // setState
    // s: 0-topState 1-subSate1 2-subState2
    baseState* setState(int s);

private:
    subState1 * mSub1;
    subState2 * mSub2;
};

class subState1 : public baseState
{
public:
    explicit subState1() {
        cout << "sub state1 entry!" << endl;
    }
    ~subState1() {
        cout << "sub state1 exit!" << endl;
    }
    void init() {
        cout << "sub state1 init." << endl;
    }
};

class subState2 : public baseState
{
public:
    explicit subState2() {
        cout << "sub state2 entry!" << endl;
    }
    ~subState2() {
        cout << "sub state2 exit!" << endl;
    }
    void init(){
        cout << "sub state2 init." << endl;
    }
};

objHoldSate::objHoldSate(baseState *bS): mState(bS), curState(bS) {
    mState->start();
}

objHoldSate::~objHoldSate() {
	if (NULL != mState) {
		delete mState;
	}
	if (NULL != curState) {
		delete curState;
	}
}

void objHoldSate::setState(int state) {
    	curState = mState->setState(state);
}

baseState::~baseState() {
	if (NULL != mSub1) {
    		delete mSub1;
	}
	if (NULL != mSub2) {
		delete mSub2;
	}
}

// Initializing a subclass in the constructor of the parent class
// will cause memory allocation to crash
void baseState::start() {
	mSub1 = new subState1();
	mSub2 = new subState2();
    	cout << "start state transtation." << endl;
}

baseState* baseState::setState(int s) {
    switch (s) {
    case 0:
        // jump to self
	cout << "this is self" << endl;
        return this;
    case 1:
        // jump to subState1
        return (baseState*)mSub1;
	cout << "this is subState1" << endl;
    case 2:
        // jump to subSate2
        return (baseState*)mSub2;
	cout << "this is subState2" << endl;
    default:
        return NULL;
    }
}

}

#endif // SIMU_H
#include "simu.h"

// using namespace std;
using namespace SIMUSTATEMACHINE;

int main()
{
    // cout << "Hello World!" << endl;
    baseState *bS = new baseState();
    objHoldSate obj(bS);
    obj.setState(1);
    subState1 *tmp = (subState1*)(obj.getCurrStatePoint());
    tmp->init();
    tmp->event3();

    obj.setState(2);
    subState2 *tmp1 = (subState2*)(obj.getCurrStatePoint());
    tmp1->init();
    tmp1->event2();

    return 0;
}