Behavioral mode - state machine mode (STATE)

1. Intent

The state pattern is an object behavior pattern. Allows an object to change its behavior when its internal state changes. The object appears to have modified its class.

For stateful objects, the complex "judgment logic" is extracted into different state objects, allowing state objects to change their behavior when their internal state changes.

A state machine is also called a finite state machine, and it consists of three parts: state, event, and action. Among them, an event is also called a transition condition. Events trigger the transition of states and the execution of actions. However, the action is not necessary, and it is possible to just transfer the state without performing any action.
For the state machine, there are three implementations.
The first implementation is called the branching logic method. Use if-else or switch-case branch logic, refer to the state transition diagram, and literally translate each state transition into code as it is. For simple state machines, this implementation is the simplest and most straightforward, and is the first choice.
The second implementation is called look-up table method. For a state machine with many states and complex state transitions, the look-up table method is more suitable. Representing the state transition diagram through a two-dimensional array can greatly improve the readability and maintainability of the code.
The third implementation is called the state pattern. For a state machine with few states and relatively simple state transition, but the business logic contained in the action triggered by the event may be more complex, we prefer this implementation method.

2. Aliases

State Machine Objects (Objects for States)

3. Advantages and disadvantages

Advantages:
The structure is clear, and the state pattern localizes the behavior related to a specific state into one state, and separates the behavior of different states, satisfying the "single responsibility principle".
Visualize state transitions and reduce interdependence between objects. Bringing different states into separate objects makes state transitions more explicit and reduces interdependencies between objects.
The status class has clear responsibilities, which is conducive to the expansion of the program. New states and transitions are easily added by defining new subclasses.
Disadvantages:
The use of state mode will inevitably increase the number of classes and objects in the system.
The structure and implementation of the state pattern are relatively complicated, and if used improperly, it will lead to confusion in the program structure and code.
The state mode does not support the opening and closing principle very well. For the state mode that can switch states, adding a new state class requires modifying the source code responsible for state transitions, otherwise it is impossible to switch to the new state, and modify the state of a state class The behavior also needs to modify the source code of the corresponding class.

4. Application scenarios

In daily development, various status switching is often encountered, such as the order status of the e-commerce system. If we disperse various states in various places, this is not conducive to management. Second, once a problem occurs, it is difficult to find the cause and fix it, and it is often prone to various bugs and loose control. At this time, we need to use the state machine mode to reasonably control the verification, processing and change of the order status.

5. Implementation steps

The state machine can be summarized into 4 elements, namely present state, condition, action and next state. This induction is mainly based on the consideration of the internal causality of the state machine. "Current state" and "condition" are the cause, and "action" and "next state" are the effect. The details are as follows:
 ①Current state: refers to the current state.
 ②Condition: Also known as "event", when a condition is met, an action will be triggered, or a state transition will be performed.
 ③ Action: The action to be executed after the condition is met. After the action is executed, it can migrate to a new state, or it can remain in the original state. Actions are not required. When the conditions are met, you can directly migrate to the new state without performing any actions.
 ④ Second state: the new state to be moved to after the condition is met. The "secondary state" is relative to the "present state". Once the "secondary state" is activated, it will transform into a new "present state".

6. Examples

#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }

/*Declare the Context class*/
class Context;
 
/*Abstract state class: define an interface to encapsulate behaviors related to a specific state of the Context*/
class State
{ public:     virtual void Handle(Context *pContext) = 0; };


/*Context class, maintaining an instance of ConcreteState subclass, which defines the current state*/
class Context
{ public:     Context(State *pState) : m_pState(pState){}     void Request()     {         if (m_pState)         {             m_pState ->Handle(this);         }     }     void ChangeState(State *pState)     {         m_pState = pState;     } private:     State *m_pState; //The State pointer here is the key to achieve a specific state };


 







 




 


class ConcreteStateA : public State
{
public:
    virtual void Handle(Context *pContext)
    {
        cout<<"I am concretestateA."<<endl;
    }
};
 
class ConcreteStateB : public State
{
public:
    virtual void Handle(Context *pContext)
    {
        cout<<"I am concretestateB."<<endl;
    }
};
 

int main()
{     State *pStateA = new ConcreteStateA();//Initialize two concrete state class objects     State *pStateB = new ConcreteStateB();     Context *pContext = new Context(pStateA); //Transfer concrete state class objects Managed by the Context class     pContext->Request();//The Context class calls the specific function of the object according to the object state Request     pContext->ChangeState(pStateB); //Change the object state     pContext->Request();



     


    SAFE_DELETE(pContext);
    SAFE_DELETE(pStateB);
    SAFE_DELETE(pStateA);
     
    return 0;
}

Guess you like

Origin blog.csdn.net/rukawashan/article/details/124574070