状态机实现

Pau*_*ulH 3 c++ state-machine

我有一个如下所述的状态机.

我们可以从两种起始状态中的一种开始,但我们必须触及握手的所有4种状态.从那里,我们可以传输数据的有效载荷或接收数据的有效载荷.然后,我们回到原来的起始状态.

握手:

- > StartingState1 - > FinalState1 - > StartingState2 - > FinalState2

- > StartingState2 - > FinalState2 - > StartingState1 - > FinalState1

有效负载转移:

- > SendPayload - > SendEnd - > StartingState?

- > ReceivePayload - > ReceiveEnd - > StartingState?

下面的代码代表了我当前的架构.不幸的是,在每个过程结束时,我没有从州内获得足够的信息来了解我应该触及的下一个状态.

有没有人对如何根据我的要求改进这种架构有任何建议?

谢谢,PaulH

class MyMachine;
class Payload;

class IState
{
    MyMachine* context_;

    IState( MyMachine* context ) : context_( context) {};

    virtual void Consume( byte data );

    void ChangeState( IState* state )
    {
        context_->SetState( state );
    }
}

class FinalState1 : IState
{
    void Consume( byte data )
    {
        // Either go to StartingState1, SendPayload, or ReceivePayload.
        // How can I tell from within the context of this state where I 
        // should go?
    }
}

class StartingState1 : IState
{
    void Consume( byte data )
    {
        if ( /*some condition*/ )
        {
            ChangeState( new FinalState1( context_ ) );
        } 
    }
}

class MyMachine
{
    IState* state_;
    Payload* payload_;

    void Start1( Mode mode )
    {
        state_ = new StartingState1( this );
    }

    void Start2( Mode mode )
    {
        state_ = new StartingState2( this );
    }

    void Consume( byte data )
    {
        state_->Consume( data );
    }

    void SetPayload( const Payload* payload )
    {
        payload_ = payload;
    }

    const Payload* GetPayload()
    {
        return payload_;
    }

    void SetState( State* state )
    {
        delete state_;
        state_ = state;
    }
}

// get a byte of data from some source
byte GetData();

void main()
{
    MyMachine machine;
    Payload payload;
    machine.SetPayload( payload );
    machine.Start1( Mode::SendPayload );

    // could also call:
    // machine.Start1( Mode::ReceivePayload );
    // machine.Start2( Mode::SendPayload );
    // machine.Start2( Mode::ReceivePayload );

    for(;;)
    {
        machine.Consume( GetData() );
    }
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*wen 5

你所拥有的并不完全代表你系统的可能状态,但它很容易转换它.您需要其他状态来表示处于状态1和未处于状态2之间的区别,并且处于状态1,同时处于状态2(对于状态2而言相同).所以你需要:

S1 S2 F1 F2 S12 F12 S21 F21
SP SE
RP RE
Run Code Online (Sandbox Code Playgroud)

与过渡

S1 --> F1
F1 --> S12
S12 --> F12
F12 --> SP or F12 --> RP

S2 --> F2
F2 --> S21
S21 --> F21
F21 --> SP or F21 --> RP

SP --> SE
RP --> RE
SE --> S1 or SE --> S2
RE --> S1 or RE --> S2
Run Code Online (Sandbox Code Playgroud)

关键的区别是引入新的状态S12,F12,S21F21.在实现方面,您几乎可以肯定地从S2导出S12,从F2导出F12,从S1导出S21,从F2导出F21并覆盖转换函数以进入正确状态.

(为所有州的首字母缩略词道歉).