Hello! Welcome to your next lesson on behavioral design patterns.
In our previous session, we explored the Strategy pattern, which allows you to define a family of interchangeable algorithms and select one at runtime. We saw how it helps organize code that performs the same task in different ways, like choosing a payment method or a parking strategy.
Today, we'll tackle the learning outcome: Apply the State pattern to allow an object to alter its behavior when its internal state changes.
At first glance, the State pattern's structure can look almost identical to the Strategy pattern's. However, their intent is fundamentally different. While Strategy deals with how an action is performed, State deals with what actions are possible and how the object behaves based on its current condition. This pattern is essential for modeling objects that move through a lifecycle of different states, a common scenario in system design interviews.
What is the State Pattern?
Many objects in software don't have static behavior. Their response to a method call depends on their internal state. Think of a smartphone: pressing the power button does one thing if the screen is off (turns it on) and another if the screen is on (locks it). This concept is formally known as a finite state machine.
The State pattern provides an object-oriented way to implement such state machines. Instead of using large if/else or switch statements within the object's methods to check the current state, we encapsulate the behavior of each state into its own class.
The State Pattern Explained and Implemented in Java | Behavioral Design Patterns | Geekific
To start, let's watch a short segment from the video 'The State Pattern Explained and Implemented in Java' by Geekific. It uses the smartphone example to introduce the core concept of state-dependent behavior and how it relates to the State pattern.
Watch from the beginning until timestamp 02:06. Focus on how the phone's response to button presses changes based on its state (Off, Locked, Ready) and the formal definition of the State pattern.
As the video explains, the State pattern lets an object alter its behavior when its internal state changes, making it seem as if the object has changed its class. This approach helps us adhere to the Single Responsibility Principle (SRP) by moving state-specific logic into separate classes and the Open/Closed Principle (OCP) by allowing us to add new states without modifying existing ones.
The Structure of the State Pattern
The pattern has three key participants:
- Context: The object whose behavior changes based on its state. It maintains a reference to an instance of a ConcreteState, which represents its current state.
- State: An interface or abstract class that defines the methods representing the state-dependent behavior. The Context interacts with its state object through this interface.
- ConcreteState: A class that implements the State interface. Each ConcreteState class provides the implementation for a particular state of the Context. Crucially, a ConcreteState can also be responsible for managing the transition of the Context to a new state.
Let's look at the structure of the pattern through a practical example: a package delivery service.
The article 'State Design Pattern in Java' from Baeldung provides a clear, step-by-step implementation. We'll use its package delivery example to understand the code structure.
Read section '4. Implementation'. Pay close attention to how the Package class acts as the Context, delegating calls to its state object. Also, notice how the concrete states (OrderedState, DeliveredState) handle the transitions by calling pkg.setState().
From this example, we see the key dynamics:
- The client code interacts only with the
Package(Context) object, calling methods likenextState(). - The
Packageobject doesn't contain anyif/elselogic. It simply delegates the call to its current state object (e.g.,state.next(this)). - The
OrderedState'snext()method contains the logic for transitioning to the next state:pkg.setState(new DeliveredState()). The state object itself controls the transition.
State vs. Strategy: A Critical Distinction
This is where many developers get confused, as the UML diagrams for both patterns are very similar. The key difference lies in their intent and dynamics.
Let's clarify this crucial distinction.
The State Pattern Explained and Implemented in Java | Behavioral Design Patterns | Geekific
The Geekific video we watched earlier has an excellent segment comparing the State and Strategy patterns. This will help solidify your understanding of when to use which.
Watch the section from 05:04 to 06:01. Focus on the differences regarding how behavior changes and how aware the individual classes (states vs. strategies) are of each other.
Here is a summary of the differences:
| Aspect | State Pattern | Strategy Pattern |
|---|---|---|
| Intent | Manages the state of an object. The object's behavior changes entirely depending on its state. | Provides different algorithms for a specific task. The algorithms can be interchanged. |
| Behavior | States encapsulate state-specific behavior. It's about what the object does. | Strategies encapsulate an algorithm. It's about how the object does something. |
| State Transition | Concrete states are aware of each other and manage the transitions from one state to the next. The transitions are often fixed. | Strategies are independent and unaware of each other. The client or Context usually selects and changes the strategy. |
| Coupling | Concrete states are often coupled to each other to facilitate transitions. | Concrete strategies are completely decoupled from one another. |
Test your understanding!
A text editor allows a user to write text.
- Scenario A: The editor can format selected text as bold, italic, or
monospace. The user chooses the format from a dropdown. - Scenario B: The editor can be in Edit Mode (where typing inserts characters) or Command Mode (where typing executes commands, like in the Vim editor).
Which scenario is better suited for the State pattern, and which for the Strategy pattern? Why?
Show answer
- Scenario A is suited for the Strategy pattern. The core task is "formatting text." Bold, italic, and monospace are different algorithms (strategies) to accomplish this task. The user (client) selects which strategy to apply.
- Scenario B is suited for the State pattern. The editor's fundamental behavior changes based on its mode (state). In Edit Mode, a key press results in a character being inserted. In Command Mode, the same key press might delete a line or save the file. The states (Edit Mode, Command Mode) dictate the object's entire behavior and manage transitions between themselves (e.g., pressing
Esctransitions from Edit to Command Mode).
LLD Application: Designing a Vending Machine
One of the classic LLD interview problems you wanted to cover is designing a vending machine. This is a perfect use case for the State pattern, as a vending machine moves through a well-defined set of states: Idle, Has Money, Dispensing, Out of Stock, etc.
Let's design one. First, it's helpful to visualize the flow using a state diagram. This shows the possible states and the events that trigger transitions between them.

Now, let's see how we can model this using the State pattern in Java. The video below provides a detailed walkthrough, which is highly relevant for an LLD interview setting.
🚀 Vending Machine System Design – LLD for Interviews & Projects 🧑💻
The video '🚀 Vending Machine System Design' from codeWithAryan directly tackles this LLD problem and explicitly uses the State pattern as the core of the solution.
Watch the following segments: Why State Pattern? (08:37 - 10:30): This explains why the State pattern is the primary choice for this problem. Core Components (17:06 - 19:28): This introduces the VendingMachineState interface and the concrete states. State Transitions (19:28 - 23:09): This is the most important part. It walks through the state diagram, explaining how the machine transitions from Idle -> HasMoney -> Selection -> Dispense based on user actions.
To complement the video, here is a clear UML class diagram and a complete code implementation for the vending machine. This shows the static structure of the classes you would design.

Finally, let's review a clean implementation of these components in Java.
The article 'State Design Pattern' from GeeksforGeeks provides a full, well-documented Java implementation for the vending machine problem.
Review the sections from 'Example of State Design Pattern' through to 'Complete code for the above example'. You don't need to read every line in detail, but scan the code to see how the VendingMachineContext, VendingMachineState, and the concrete state classes are implemented. This reinforces what you saw in the video.
In a Spring Boot application, you could implement the concrete state classes as singleton beans. The VendingMachine (Context) could then have the current state injected, or it could fetch the required state bean from the application context when a transition occurs.
Conclusion
You've now added another powerful behavioral pattern to your LLD toolkit. The State pattern is your go-to solution when an object's behavior is dictated by its internal state.
Key Takeaways:
- Purpose: The State pattern allows an object to change its behavior when its internal state changes, by encapsulating state-specific logic into separate classes.
- Problem Solved: It helps you avoid complex conditional logic (
if/else,switch) for managing states, leading to cleaner code that follows SOLID principles. - Core Components: It consists of a Context (the stateful object), a State interface, and ConcreteState classes that implement behavior and manage transitions.
- State vs. Strategy: Remember the key difference in intent. State is about what an object is (its state), while Strategy is about how an object does something (its algorithm).
- Interview Application: It is perfectly suited for designing stateful systems like vending machines, ATMs, elevators, and document workflows.
In our next lesson, we will cover the Template Method pattern. This pattern provides a way to define the skeleton of an algorithm in a base class, allowing subclasses to redefine certain steps without changing the algorithm's overall structure. It offers a different approach to code reuse and variability compared to the State and Strategy patterns.