C++ State Pattern Example

1. Definition

The State Design Pattern allows an object to change its behavior when its internal state changes. The object will appear to change its class. Instead of implementing states with a series of conditional statements, each state is represented with a separate class.

2. Problem Statement

Imagine you have an object with multiple states, and its behavior changes based on its current state. Using conditional statements (like if-else or switch-case) to handle these state changes can lead to tangled, hard-to-maintain code, especially as the number of states or behaviors increases.

3. Solution

The State Pattern suggests representing each state as a separate class. These state-specific classes handle state-specific behavior. A context class is also provided which maintains an instance of the current state and forwards requests to the state object.

4. Real-World Use Cases

1. Vending machines which have states like idle, processing, dispensing, etc.

2. Traffic lights which change states between red, green, and yellow.

3. Game characters that can be normal, powered-up, or vulnerable.

5. Implementation Steps

1. Define a State interface defining an action.

2. Implement concrete state classes for each state.

3. Create a context class that holds the current state and allows switching of states.

6. Implementation in C++

// State Interface
class State {
public:
    virtual void handle() = 0;
};
// Concrete States
class OnState : public State {
public:
    void handle() override {
        std::cout << "Light is ON" << std::endl;
    }
};
class OffState : public State {
public:
    void handle() override {
        std::cout << "Light is OFF" << std::endl;
    }
};
// Context Class
class LightSwitch {
    State* state; // Holds the current state
public:
    LightSwitch() {
        state = new OffState();
    }
    void setState(State* newState) {
        state = newState;
    }
    void handle() {
        state->handle();
    }
};
// Example Usage
int main() {
    LightSwitch light;
    light.handle(); // Light is initially OFF
    light.setState(new OnState());
    light.handle(); // Now light is ON
    return 0;
}

Output:

Light is OFF
Light is ON

Explanation:

1. We start by defining a State interface with a handle method which all concrete state classes must implement.

2. OnState and OffState are two concrete implementations of the State representing two possible states.

3. The LightSwitch context class maintains a reference to the current state and can switch between states using setState.

4. In the example, initially, the light is OFF. We then switch its state to ON and the output reflects the change in state.

7. When to use?

Use the State pattern when:

1. An object's behavior depends on its state, and it must change its behavior at runtime depending on that state.

2. Operations have large, multi-part conditional statements that depend on the object's state. This state is usually represented by one or several enumerated constants.


Comments