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:
Strategy Design Pattern in Java
Next article icon

State Design Pattern in Java

Last Updated : 10 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

The State design pattern in Java is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes. It achieves this by encapsulating the object's behavior within different state objects, and the object itself dynamically switches between these state objects depending on its current state.

State-Design-Pattern-in-Java

Important Topics for State Design Pattern in Java

  • What is a State Design Pattern in Java?
  • Components of State Design Pattern in Java
  • Communication between the components
  • Real-World Analogy of State Design Pattern in Java
  • Example of State Design Pattern in Java
  • When to use the State Design Pattern in Java
  • When not to use the State Design Pattern in Java

What is a State Design Pattern in Java?

The State Design Pattern is a behavioral design pattern that allows an object to change its behavior when its internal state changes. This pattern is particularly useful when an object's behavior depends on its state, and the state can change during the object's lifecycle.

This pattern focuses on managing state transitions and coordinating state-specific behaviors.

Components of State Design Pattern in Java

Below are the components of State Design Pattern in Java:

1. Context

The Context is the class that contains the object whose behavior changes based on its internal state. It maintains a reference to the current state object that represents the current state of the Context. The Context provides an interface for clients to interact with and typically delegates state-specific behavior to the current state object.

2. State Interface or Base Class

The State interface or base class defines a common interface for all concrete state classes. This interface typically declares methods that represent the state-specific behavior that the Context can exhibit. It allows the Context to interact with state objects without knowing their concrete types.

3. Concrete States

Concrete state classes implement the State interface or extend the base class. Each concrete state class encapsulates the behavior associated with a specific state of the Context. These classes define how the Context behaves when it is in their respective states.

componentdiagramstate

Communication between the components

In the State design pattern, the communication between the components typically follows these steps:

  • Step1: Client InteractionThe client interacts with the Context object, either directly or indirectly, by invoking methods on it.
  • Step2 :Behavior DelegationWhen the client triggers an action or requests a behavior from the Context, the Context delegates the responsibility to its current State object.
  • Step3 :State-specific Behavior ExecutionThe current State object receives the delegated request and executes the behavior associated with its particular state.
  • Step4 :Possible State TransitionDepending on the logic implemented within the State object or controlled by the Context, a state transition may occur.
  • Step5 :Update of Current StateIf a state transition occurs, the Context updates its reference to the new State object, reflecting the change in its internal state.
  • Step6 :Continued InteractionThe client continues to interact with the Context as needed, and the process repeats, with behavior delegation to the appropriate State object based on the current state of the Context.

This communication flow ensures that the Context and State objects work together seamlessly to achieve dynamic behavior changes based on the internal state of the Context. The Context manages the state and delegates behavior to the current State object, while the State objects encapsulate state-specific behavior and handle transitions between states as necessary

Real-World Analogy of State Design Pattern in Java

Imagine a traffic light as a robot. It has different moods like "Stop" (Red), "Get Ready" (Yellow), and "Go" (Green).

  • The robot changes its mood based on the time or if cars are waiting.
  • When it's "Stop", cars stop, and people can walk. When it's "Get Ready", it's about to change. And when it's "Go", cars can drive.
  • This setup makes it easy to add new moods or change how the robot behaves without messing up everything else. So, it's like having a robot traffic light that knows when to stop, get ready, or go!

Example of State Design Pattern in Java

Imagine a vending machine that sells various products. The vending machine needs to manage different states such as ready to serve, waiting for product selection, processing payment, and handling out-of-stock situations. Design a system that models the behavior of this vending machine efficiently.

How State Design Pattern will help while building this system:

  • Modelling Different States:
    • The State design pattern allows us to model each state of the vending machine (e.g., ready, product selected, payment pending, out of stock) as a separate class.
    • This separation of concerns makes the codebase more organized and maintainable.
  • Encapsulation of State-specific Behavior:
    • Each state class encapsulates its specific behavior. For example, the ReadyState class handles the behavior when the machine is ready for product selection, while the PaymentPendingState class handles behavior related to processing payments.
    • This encapsulation helps in managing complex state-dependent logic and promotes better code readability.
  • Dynamic State Transition:
    • The State pattern facilitates dynamic state transitions. For instance, when a user selects a product, the vending machine transitions from the ReadyState to the ProductSelectedState, and further transitions occur based on the user's actions.
    • This dynamic behavior allows the vending machine to adapt to different scenarios and handle state changes seamlessly.
  • Code Reusability:
    • By implementing states as separate classes, the State pattern promotes code reusability. States can be reused across different contexts or vending machine implementations without modification.
    • This reusability reduces code duplication and promotes a more modular and scalable design.
  • Maintainability and Flexibility:
    • As the vending machine requirements evolve or new states need to be added, the State pattern makes it easier to extend the system.
    • Modifications or additions to state-specific behavior can be made without affecting other parts of the codebase, leading to improved maintainability and flexibility.

User Interaction with the System

User interactions with the vending machine trigger state transitions. For example, when a user inserts money, the vending machine transitions from the "ReadyState" to the "PaymentPendingState." Similarly, when a product is selected, the vending machine transitions to the "ProductSelectedState." If a product is out of stock, the vending machine transitions to the "OutOfStockState."

ClassDiagramState

Below is the code of above problem statement using State Design Pattern in Java:

Let’s break down into the component wise code in Java:

1. Context(VendingMachineContext)

The context is responsible for maintaining the current state of the vending machine and delegating state-specific behavior to the appropriate state object.

Java
public class VendingMachineContext {
    private VendingMachineState state;

    public void setState(VendingMachineState state) {
        this.state = state;
    }

    public void request() {
        state.handleRequest();
    }
}

2. State Interface (VendingMachineState)

This interface defines the contract that all concrete state classes must implement. It typically contains a method or methods representing the behavior associated with each state of the vending machine.

Java
public interface VendingMachineState {
    void handleRequest();
}

3. Concrete States (Specific Vending Machine States)

Concrete state classes represent specific states of the vending machine, such as "ReadyState," "ProductSelectedState," and "OutOfStockState." Each concrete state class implements the behavior associated with its respective state, like allowing product selection, processing payment, or displaying an out-of-stock message.

Java
public class ReadyState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Ready state: Please select a product.");
    }
}

public class ProductSelectedState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Product selected state: Processing payment.");
    }
}

public class PaymentPendingState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Payment pending state: Dispensing product.");
    }
}

public class OutOfStockState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Out of stock state: Product unavailable. Please select another product.");
    }
}

Complete code for the above example

Below is the complete code for the above example:

Java
interface VendingMachineState {
    void handleRequest();
}

class ReadyState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Ready state: Please select a product.");
    }
}

class ProductSelectedState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Product selected state: Processing payment.");
    }
}

class PaymentPendingState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Payment pending state: Dispensing product.");
    }
}

class OutOfStockState implements VendingMachineState {
    @Override
    public void handleRequest() {
        System.out.println("Out of stock state: Product unavailable. Please select another product.");
    }
}

class VendingMachineContext {
    private VendingMachineState state;

    public void setState(VendingMachineState state) {
        this.state = state;
    }

    public void request() {
        state.handleRequest();
    }
}

public class Main {
    public static void main(String[] args) {
        // Create context
        VendingMachineContext vendingMachine = new VendingMachineContext();

        // Set initial state
        vendingMachine.setState(new ReadyState());

        // Request state change
        vendingMachine.request();

        // Change state
        vendingMachine.setState(new ProductSelectedState());

        // Request state change
        vendingMachine.request();

        // Change state
        vendingMachine.setState(new PaymentPendingState());

        // Request state change
        vendingMachine.request();

        // Change state
        vendingMachine.setState(new OutOfStockState());

        // Request state change
        vendingMachine.request();
    }
}
Output
Ready state: Please select a product.
Product selected state: Processing payment.
Payment pending state: Dispensing product.
Out of stock state: Product unavailable. Please select another product.

Communication between Components in the above example:

  • When a user interacts with the vending machine (Context), such as inserting money or selecting a product, the vending machine delegates the responsibility of handling the interaction to the current state object.
  • The current state object (e.g., "ReadyState" or "ProductSelectedState") executes the behavior associated with that state, such as processing the payment or dispensing the selected product.
  • Depending on the outcome of the interaction and the logic implemented within the current state object, the vending machine may transition to a different state.
  • The process continues as the user interacts further with the vending machine, with behavior delegated to the appropriate state object based on the current state of the vending machine.

When to use the State Design Pattern in Java

The State design pattern is beneficial when you encounter situations with objects whose behavior changes dynamically based on their internal state. Here are some key indicators:

  • Multiple states with distinct behaviors: If your object exists in several states (e.g., On/Off, Open/Closed, Started/Stopped), and each state dictates unique behaviors, the State pattern can encapsulate this logic effectively.
  • Complex conditional logic: When conditional statements (if-else or switch-case) become extensive and complex within your object, the State pattern helps organize and separate state-specific behavior into individual classes, enhancing readability and maintainability.
  • Frequent state changes: If your object transitions between states frequently, the State pattern provides a clear mechanism for managing these transitions and their associated actions.
  • Adding new states easily: If you anticipate adding new states in the future, the State pattern facilitates this by allowing you to create new state classes without affecting existing ones.

When not to use the State Design Pattern in Java

While the State pattern offers advantages, it's not always the best solution. Here are some cases where it might be overkill:

  • Few states with simple behavior: If your object has only a few simple states with minimal behavioral differences, the overhead of the State pattern outweighs its benefits. In such cases, simpler conditional logic within the object itself might suffice.
  • Performance-critical scenarios: The pattern can introduce additional object creation and method calls, potentially impacting performance. If performance is paramount, a different approach might be more suitable.
  • Over-engineering simple problems: Don't apply the pattern just for the sake of using a design pattern. If your logic is clear and maintainable without it, stick with the simpler solution.

Ultimately, the decision to use the State pattern depends on the specific context and complexity of your problem. Consider the trade-offs between code organization, maintainability, performance, and development effort before applying it.


Next Article
Strategy Design Pattern in Java

S

sanketsay9qs
Improve
Article Tags :
  • Design Pattern
  • System Design
  • Java Design Patterns

Similar Reads

    Strategy Design Pattern in Java
    The Strategy Design Pattern in Java defines a family of algorithms, encapsulates each one, and makes them interchangeable, allowing clients to switch algorithms dynamically without altering the code structure. Important Topics for Strategy Design Pattern in JavaWhat is the Strategy Design Pattern in
    13 min read
    Strategy Method Design Pattern in Java
    Strategy method or Strategy Design Pattern is a behavioral design pattern in Java that defines a family of algorithms, encapsulates each algorithm, and makes them interchangeable. It lets the client algorithm vary independently from the objects that use it. This pattern is useful when you have a fam
    11 min read
    State Design Pattern
    The State design pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes. It achieves this by encapsulating the object's behavior within different state objects, and the object itself dynamically switches between these state objects
    11 min read
    Template Method Design Pattern in Java
    Template Design Pattern or Template Method is the behavioral design pattern that defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure. This pattern falls under the category of the "behavioral" design patter
    10 min read
    State Method Design Patterns in JavaScript
    State method or State Design Patterns is a pattern that allows an object to alter its behavior when internal state changes occur. This pattern is used when an object wants to change its state dynamically. When we want to change behavior of object it internally uses if-else block to perform actions.
    4 min read
    Strategy Design Pattern
    The Strategy Design Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable, allowing clients to switch algorithms dynamically without altering the code structure.Table of ContentWhat is the Strategy Design Pattern?Components of the Strategy Design PatternCommun
    11 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