Skip to content
geeksforgeeks
  • Tutorials
    • Python
    • Java
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • Software and Tools
    • School Learning
    • Practice Coding Problems
  • Go Premium
  • System Design Tutorial
  • What is System Design
  • System Design Life Cycle
  • High Level Design HLD
  • Low Level Design LLD
  • Design Patterns
  • UML Diagrams
  • System Design Interview Guide
  • Scalability
  • Databases
Open In App
Next Article:
Factory Method Pattern | C++ Design Patterns
Next article icon

State Method Design Pattern | C++ Design Patterns

Last Updated : 20 Jun, 2024
Summarize
Comments
Improve
Suggest changes
Share
Like Article
Like
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.

When-Does-a-Distributed-System-Need-ZooKeeper-copy-7

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.

Important Topics for the State Method Design Pattern in C++ Design Patterns

  • Example of State Pattern in C++
  • Advantages of the State Pattern in C++ Design Patterns
  • Disadvantages of the State Pattern in C++ Design Patterns
  • Conclusion

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.


Next Article
Factory Method Pattern | C++ Design Patterns

R

rudra1807raj
Improve
Article Tags :
  • Design Pattern
  • Geeks Premier League
  • System Design
  • Geeks Premier League 2023
  • C++ Design Pattern

Similar Reads

    Strategy Method Design Pattern | C++ Design Patterns
    Strategy Pattern is a behavioral design pattern that defines a family of interchangeable algorithms and allows them to be used interchangeably within a context. This pattern enables the algorithm to be selected at runtime, providing flexibility and promoting code reusability. Important Topics for th
    4 min read
    Template Method Design Pattern | C++ Design Patterns
    Template Method Pattern introduces a template in a superclass that defines the steps of an algorithm. These steps may include both common tasks shared among subclasses and specific tasks that need customization. Subclasses then implement or override these steps to modify the algorithm according to t
    7 min read
    Memento Design Pattern | C++ Design Patterns
    Memento Design Pattern is a behavioral design pattern that provides a mechanism for capturing an object's internal state and restoring it to that state at a later time. This pattern is useful when we need to implement features like undo/redo functionality or when we want to save and restore an objec
    7 min read
    Factory Method Pattern | C++ Design Patterns
    Factory Method Pattern provides an interface for creating objects but leaves the actual object instantiation to derived classes. This allows for flexibility in object creation and promotes loose coupling between the client code and the concrete products.Factory Method Pattern | C++ Design PatternsTa
    8 min read
    State Method - Python Design Patterns
    State method is Behavioral Design Pattern that allows an object to change its behavior when there occurs a change in its internal state. It helps in implementing the state as a derived class of the state pattern interface. If we have to change the behavior of an object based on its state, we can hav
    4 min read
    Mediator Design Pattern vs. Observer Design Pattern
    The Mediator Design Pattern and Observer Design Pattern are both key design patterns that help manage object communication but differ in approach. The Mediator Pattern centralizes interactions, where objects communicate through a mediator, reducing dependencies. In contrast, the Observer Pattern all
    5 min read
`; $(commentSectionTemplate).insertBefore(".article--recommended"); } loadComments(); }); }); function loadComments() { if ($("iframe[id*='discuss-iframe']").length top_of_element && top_of_screen articleRecommendedTop && top_of_screen articleRecommendedBottom)) { if (!isfollowingApiCall) { isfollowingApiCall = true; setTimeout(function(){ if (loginData && loginData.isLoggedIn) { if (loginData.userName !== $('#followAuthor').val()) { is_following(); } else { $('.profileCard-profile-picture').css('background-color', '#E7E7E7'); } } else { $('.follow-btn').removeClass('hideIt'); } }, 3000); } } }); } $(".accordion-header").click(function() { var arrowIcon = $(this).find('.bottom-arrow-icon'); arrowIcon.toggleClass('rotate180'); }); }); window.isReportArticle = false; function report_article(){ if (!loginData || !loginData.isLoggedIn) { const loginModalButton = $('.login-modal-btn') if (loginModalButton.length) { loginModalButton.click(); } return; } if(!window.isReportArticle){ //to add loader $('.report-loader').addClass('spinner'); jQuery('#report_modal_content').load(gfgSiteUrl+'wp-content/themes/iconic-one/report-modal.php', { PRACTICE_API_URL: practiceAPIURL, PRACTICE_URL:practiceURL },function(responseTxt, statusTxt, xhr){ if(statusTxt == "error"){ alert("Error: " + xhr.status + ": " + xhr.statusText); } }); }else{ window.scrollTo({ top: 0, behavior: 'smooth' }); $("#report_modal_content").show(); } } function closeShareModal() { const shareOption = document.querySelector('[data-gfg-action="share-article"]'); shareOption.classList.remove("hover_share_menu"); let shareModal = document.querySelector(".hover__share-modal-container"); shareModal && shareModal.remove(); } function openShareModal() { closeShareModal(); // Remove existing modal if any let shareModal = document.querySelector(".three_dot_dropdown_share"); shareModal.appendChild(Object.assign(document.createElement("div"), { className: "hover__share-modal-container" })); document.querySelector(".hover__share-modal-container").append( Object.assign(document.createElement('div'), { className: "share__modal" }), ); document.querySelector(".share__modal").append(Object.assign(document.createElement('h1'), { className: "share__modal-heading" }, { textContent: "Share to" })); const socialOptions = ["LinkedIn", "WhatsApp","Twitter", "Copy Link"]; socialOptions.forEach((socialOption) => { const socialContainer = Object.assign(document.createElement('div'), { className: "social__container" }); const icon = Object.assign(document.createElement("div"), { className: `share__icon share__${socialOption.split(" ").join("")}-icon` }); const socialText = Object.assign(document.createElement("span"), { className: "share__option-text" }, { textContent: `${socialOption}` }); const shareLink = (socialOption === "Copy Link") ? Object.assign(document.createElement('div'), { role: "button", className: "link-container CopyLink" }) : Object.assign(document.createElement('a'), { className: "link-container" }); if (socialOption === "LinkedIn") { shareLink.setAttribute('href', `https://www.linkedin.com/sharing/share-offsite/?url=${window.location.href}`); shareLink.setAttribute('target', '_blank'); } if (socialOption === "WhatsApp") { shareLink.setAttribute('href', `https://api.whatsapp.com/send?text=${window.location.href}`); shareLink.setAttribute('target', "_blank"); } if (socialOption === "Twitter") { shareLink.setAttribute('href', `https://twitter.com/intent/tweet?url=${window.location.href}`); shareLink.setAttribute('target', "_blank"); } shareLink.append(icon, socialText); socialContainer.append(shareLink); document.querySelector(".share__modal").appendChild(socialContainer); //adding copy url functionality if(socialOption === "Copy Link") { shareLink.addEventListener("click", function() { var tempInput = document.createElement("input"); tempInput.value = window.location.href; document.body.appendChild(tempInput); tempInput.select(); tempInput.setSelectionRange(0, 99999); // For mobile devices document.execCommand('copy'); document.body.removeChild(tempInput); this.querySelector(".share__option-text").textContent = "Copied" }) } }); // document.querySelector(".hover__share-modal-container").addEventListener("mouseover", () => document.querySelector('[data-gfg-action="share-article"]').classList.add("hover_share_menu")); } function toggleLikeElementVisibility(selector, show) { document.querySelector(`.${selector}`).style.display = show ? "block" : "none"; } function closeKebabMenu(){ document.getElementById("myDropdown").classList.toggle("show"); }
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences