Open In App

State Method Design Pattern | C++ Design Patterns

Last Updated : 05 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In software design, managing the behavior of an object according to its internal state is a common issue. The state pattern addresses this issue by allowing an object to alter its behavior every time its internal state changes.

state-method

This pattern encapsulates each state in a separate class, which makes it easier to add new states and modify existing states without altering the object’s code directly. This pattern is useful when an object transitions between different states, with each transition triggering specific actions.

Example of State Pattern in C++

Problem Statement:

We have to design a simple traffic light system. The traffic light system consists of different states: Red, Yellow, and Green and the behavior of the traffic light is determined by its current state.

Key Components of the State Pattern in C++

The State Pattern consists of the following key components:

  • Context: This is the class that has a state and assigns the state-specific behavior to different state objects.
  • State: The abstract base class or interface that defines a common interface for all concrete states. Each concrete state implements specific behaviors associated with a particular state.
  • ConcreteState: These are the classes that inherit from the State class and provide the specific implementations for the behaviors associated with a particular state.

Implementation of above State Pattern in C++:

TrafficLightState(State Interface):This is an abstract class that serves as the interface for all concrete states. It declares a pure virtual function “handle()”, which is responsible for defining the behavior of a particular state.

C++




// State Interface
class TrafficLightState {
public:
    virtual void handle() = 0;
};


RedState, YellowState, GreenState(Concrete States):These are the concrete classes that implement the “TrafficLightState” interface. Each class provides a specific implementation for the handle() function, representing the behavior associated with the corresponding traffic light color.

C++




// Concrete States
class RedState : public TrafficLightState {
public:
    void handle() override {
        std::cout << "Traffic Light is Red\n";
    }
};
 
class YellowState : public TrafficLightState {
public:
    void handle() override {
        std::cout << "Traffic Light is Yellow\n";
    }
};
 
class GreenState : public TrafficLightState {
public:
    void handle() override {
        std::cout << "Traffic Light is Green\n";
    }
};


TrafficLight(Context):The TrafficLight class has a member variable state of type TrafficLightState*, representing the current state of the traffic light. Initially, it sets the state to a default state (in this case, RedState).

  • “setState(TrafficLightState *newState)” function allows changing the current state to the specified state.
  • “change()” function invokes the “handle()” function of the current state, effectively executing the behavior associated with that state.

When the change() function is called, it invokes the handle() function of the current state (state->handle()).Since the state is initially set to RedState, the first invocation of change() prints “Traffic Light is Red.”When the state is later changed to GreenState using setState(new GreenState()), then, the next time change() is invoked it prints “Traffic Light is Green,” showing the updated behavior of the new state.

C++




// Context
class TrafficLight {
private:
    TrafficLightState *state;
 
public:
    TrafficLight() : state(new RedState()) {}
 
    void setState(TrafficLightState *newState) {
        delete state;
        state = newState;
    }
 
    void change() {
        state->handle();
    }
};


Main Function:An instance of “TrafficLight” is created, and its initial state is “RedState”.The “change()” function is called, and it prints “Traffic Light is Red” since the initial state is “RedState”.The state is then changed to “GreenState” using the “setState(new GreenState())” function.The “change()” function is called again, and it prints “Traffic Light is Green,” reflecting the new state.

C++




int main() {
    TrafficLight trafficLight;
 
    trafficLight.change();  // Initial state: Red
    trafficLight.setState(new GreenState());
    trafficLight.change();  // State changed to Green
 
    return 0;
}


Below is the complete combined code of the above example:

C++




#include <iostream>
 
// State Interface
class TrafficLightState {
public:
    virtual void handle() = 0;
};
 
// Concrete States
class RedState : public TrafficLightState {
public:
    void handle() override
    {
        std::cout << "Traffic Light is Red\n";
    }
};
 
class YellowState : public TrafficLightState {
public:
    void handle() override
    {
        std::cout << "Traffic Light is Yellow\n";
    }
};
 
class GreenState : public TrafficLightState {
public:
    void handle() override
    {
        std::cout << "Traffic Light is Green\n";
    }
};
 
// Context
class TrafficLight {
private:
    TrafficLightState* state;
 
public:
    TrafficLight()
        : state(new RedState())
    {
    }
 
    void setState(TrafficLightState* newState)
    {
        delete state;
        state = newState;
    }
 
    void change() { state->handle(); }
};
 
int main()
{
    TrafficLight trafficLight;
 
    trafficLight.change(); // Initial state: Red
    trafficLight.setState(new GreenState());
    trafficLight.change(); // State changed to Green
 
    return 0;
}


Output

Traffic Light is Red
Traffic Light is Green



Diagrammatical Representation of the State Pattern in C++

State

  • The “TrafficLight” class acts as a context that has a state. The state can be changed using the “setState” method.
  • The “TrafficLightState” is an abstract class that defines the common interface for all concrete states. It declares the “handle()” method, which represents the behavior associated with a specific state.
  • The “RedState”, “YellowState”, and “GreenState” classes are concrete implementations of states. They inherit from “TrafficLightState” and provide specific behaviors for handling the traffic light in different states.
  • The “TrafficLight” class interacts with the current state through the “handle()” method, which allows the traffic light to exhibit different behaviors based on its internal state.

This diagram illustrates how a traffic light can change its behavior (color) by transitioning between different states (Red, Yellow, Green). Each state class defines what should happen when the traffic light is in that specific color. The “TrafficLight” class manages the state and delegates the handling of behaviors to the current state.

Advantages of the State Pattern in C++ Design Patterns

  • Clean Code: The State Pattern promotes cleaner code by encapsulating each state’s behavior within its own class, making the code more modular and maintainable.
  • Flexibility: It allows for easy addition of new states without modifying existing code. Each state is independent and can be added or modified without affecting other states.
  • Readability: The pattern enhances code readability by clearly defining the state transitions and associated behaviors in a structured manner.
  • Scalability: The pattern scales well as the number of states and state-specific behaviors increases. It provides a scalable and maintainable solution for managing complex systems with a number of states.
  • Facilitates Testing: Testing becomes more manageable as each state can be tested independently. You can focus on testing the specific behaviors associated with each state without worrying about interactions with other states.

Disadvantages of the State Pattern in C++ Design Patterns

  • Complexity: The State Pattern introduces additional classes, which makes the codebase more complex, especially for simple state transitions.
  • Increased Number of Classes: The State Pattern can lead to a larger number of classes, which may be overwhelming for small projects.
  • Learning Curve: Developers unfamiliar with the State Pattern might find it challenging to understand and implement initially.
  • Overhead: There might be some overhead in managing state transitions, which could impact performance in certain situations.

Conclusion

The State Pattern is a powerful tool in C++ for managing the behavior of objects based on their internal state. By encapsulating states in separate classes, the pattern promotes modularity and maintainability. While it may introduce some complexity, the benefits in terms of code clarity and extensibility often exceed the drawbacks. When used carfully, the State Pattern can lead to more flexible and scalable software designs.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads