State machine representation
I want to implement the GUI as a state machine. I think there are some benefits and some drawbacks of doing this, but this is not the topic of this questions.
After some reading about this I found several ways of modeling a state machine in C++ and I stuck on 2, but I don't know what method may fit better for GUI modeling.
Represent the State Machine as a list of states with following methods:
OnEvent(...);
OnEnterState(...);
OnExitState(...);
From StateMachine::OnEvent(...)
I forward the event to CurrentState::OnEvent(...)
and here the decision to make a transition or not is made. On transition I call CurrentState::OnExitState(...)
, NewState::OnEnterState()
and CurrentState = NewState;
With this approach the state will be tightly coupled with actions, but State
might get complicated when from one state I can go to multiple states and I have to take different actions for different transitions.
Represent the state machine as list of transitions with following properties:
InitialState
FinalState
OnEvent(...)
DoTransition(...)
From StateMachine::OnEvent(...)
I forward the event to all transitions where InitialState
has same value as CurrentState
in the state machine. If the transition condition is met the loop is stopped, DoTransition
method is called and CurrentState
set to Transition::FinalState
.
With this approach Transition
will be very simple, but the number of transition count might get very high. Also it will become harder to track what actions will be done when one state receives an event.
What approach do you think is better for GUI modeling. Do you know other representations that may be better for my problem?
Here is a third option:
symbol
(see below) OnEvent
method which returns a symbol
From StateMachine::OnEvent(...)
events are forwarded to State::OnEvent
which returns a symbol
- a result of execution. StateMachine
then based on current state and returned symbol decides whether
OnExitState
and OnEnterState
is called for a corresponsing states Example matrix for 3 states and 3 symbols
0 1 2
1 2 0
2 0 1
In this example if if machine is in any od the states (0,1,2)
and State::OnEvent
returns symbol 0
(first row in the matrix) - it stays in the same state
Second row says, that if current state is 0
and returned symbol is 1
transition is made to state 1
. For state 1
-> state 2
and for state 2
-> state 0
.
Similary third row says that for symbol 2
, state 0
-> state 2
, state 1
-> state 0
, state 2
-> state 1
The point of this being:
symbols
will likely be much lower than that of states. DB_ERROR
differently to NETWORK_ERROR
you just change the transition table and don't touch states implementation. I don't know if this is the kind of answer you are expecting, but I use to deal with such state machines in a straightforward way.
Use a state variable of an enumerated type (the possible states). In every event handler of the GUI, test the state value, for instance using a switch statement. Do whatever processing there needs to be accordingly and set the next value of the state.
Lightweight and flexible. Keeping the code regular makes it readable and "formal".
I'd personally prefer the first method you said. I find the second one to be quite counter-intuitive and overly complicated. Having one class for each state is simple and easy, if then you set the correct event handlers in OnEnterState and remove them in OnExitState your code will be clean and everything will be self contained in the corresponding state, allowing for an easy read.
You will also avoid having huge switch statements to select the right event handler or procedure to call as everything a state does is perfectly visible inside the state itself thus making the state machine code short and simple.
Last but not least, this way of coding is an exact translation from the state machine draw to whatever language you'll use.
链接地址: http://www.djcxy.com/p/53196.html上一篇: 基于协程的状态机
下一篇: 状态机表示