State Design Pattern (original) (raw)

Last Updated : 13 May, 2026

The State Design Pattern is a behavioral design pattern that lets an object alter its behavior when its internal state changes. It encapsulates state-specific behavior into separate state classes, allowing the object to manage state transitions cleanly. This avoids complex conditional statements and makes the system more maintainable and flexible.

**Example: a vending machine responds differently based on state (item selected, money paid and item dispensed).

state_design_pattern

State Design Pattern

Working

The pattern works by encapsulating each possible state in a separate class and letting the context object delegate behavior to the current state.

Real Life Software Examples

The State pattern can be observed in many real-world applications where an object’s behavior changes depending on its current condition.

Uses

The State pattern is commonly used when an object’s behavior depends on its state and changes over time.

Components

The State pattern is structured around components that separate state-specific behavior from the main object, allowing behavior to change dynamically at runtime.

componentdiagramstate

Implementation Example

Problem Statement

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.

**Applying the State Design Pattern in This System

**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

Let’s break down into the component wise code:

**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.

C++ `

public class VendingMachineContext { private VendingMachineState state;

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

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

}

Java

public class VendingMachineContext { private VendingMachineState state;

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

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

}

Python

class VendingMachineContext: def init(self): self._state = None

def set_state(self, state):
    self._state = state

def request(self):
    self._state.handle_request()

JavaScript

class VendingMachineContext { #private VendingMachineState state;

constructor() {
    this.state = null;
}

setState(state) {
    this.state = state;
}

request() {
    this.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.

C++ `

public interface VendingMachineState { void handleRequest(); }

Java

/* Public interface VendingMachineState */ public interface VendingMachineState { void handleRequest(); }

Python

""" Public interface VendingMachineState """ from abc import ABC, abstractmethod

class VendingMachineState(ABC): @abstractmethod def handleRequest(self): pass

JavaScript

/* Public interface VendingMachineState */ class VendingMachineState { handleRequest() { // Handle request logic here } }

`

**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.

C++ `

#include #include using namespace std;

class VendingMachineState { public: virtual void handleRequest() = 0; };

class ReadyState : public VendingMachineState { public: void handleRequest() override { cout << "Ready state: Please select a product." << endl; } };

class ProductSelectedState : public VendingMachineState { public: void handleRequest() override { cout << "Product selected state: Processing payment." << endl; } };

class PaymentPendingState : public VendingMachineState { public: void handleRequest() override { cout << "Payment pending state: Dispensing product." << endl; } };

class OutOfStockState : public VendingMachineState { public: void handleRequest() override { cout << "Out of stock state: Product unavailable. Please select another product." << endl; } };

Java

import java.util.ArrayList;

// VendingMachineState interface interface VendingMachineState { void handleRequest(); }

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

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

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

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

// VendingMachine class class VendingMachine { private VendingMachineState currentState;

public VendingMachine() {
    this.currentState = new ReadyState();
}

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

public void handleRequest() {
    currentState.handleRequest();
}

}

// Main class public class Main { public static void main(String[] args) { VendingMachine vendingMachine = new VendingMachine(); vendingMachine.handleRequest(); vendingMachine.setState(new ProductSelectedState()); vendingMachine.handleRequest(); vendingMachine.setState(new PaymentPendingState()); vendingMachine.handleRequest(); vendingMachine.setState(new OutOfStockState()); vendingMachine.handleRequest(); } }

Python

from abc import ABC, abstractmethod

class VendingMachineState(ABC): @abstractmethod def handle_request(self): pass

class ReadyState(VendingMachineState): def handle_request(self): print('Ready state: Please select a product.')

class ProductSelectedState(VendingMachineState): def handle_request(self): print('Product selected state: Processing payment.')

class PaymentPendingState(VendingMachineState): def handle_request(self): print('Payment pending state: Dispensing product.')

class OutOfStockState(VendingMachineState): def handle_request(self): print('Out of stock state: Product unavailable. Please select another product.')

JavaScript

class VendingMachineState {}

class ReadyState extends VendingMachineState { handleRequest() { console.log('Ready state: Please select a product.'); } }

class ProductSelectedState extends VendingMachineState { handleRequest() { console.log('Product selected state: Processing payment.'); } }

class PaymentPendingState extends VendingMachineState { handleRequest() { console.log('Payment pending state: Dispensing product.'); } }

class OutOfStockState extends VendingMachineState { handleRequest() { console.log('Out of stock state: Product unavailable. Please select another product.'); } }

`

Complete code for the above example

The complete code for the above example is:

C++ `

#include

class VendingMachineState { public: virtual void handleRequest() = 0; };

class ReadyState : public VendingMachineState { public: void handleRequest() override { std::cout << "Ready state: Please select a product." << std::endl; } };

class ProductSelectedState : public VendingMachineState { public: void handleRequest() override { std::cout << "Product selected state: Processing payment." << std::endl; } };

class PaymentPendingState : public VendingMachineState { public: void handleRequest() override { std::cout << "Payment pending state: Dispensing product." << std::endl; } };

class OutOfStockState : public VendingMachineState { public: void handleRequest() override { std::cout << "Out of stock state: Product unavailable. Please select another product." << std::endl; } };

class VendingMachineContext { private: VendingMachineState* state; public: void setState(VendingMachineState* state) { this->state = state; } void request() { state->handleRequest(); } };

int main() { VendingMachineContext vendingMachine;

vendingMachine.setState(new ReadyState());
vendingMachine.request();

vendingMachine.setState(new ProductSelectedState());
vendingMachine.request();

vendingMachine.setState(new PaymentPendingState());
vendingMachine.request();

vendingMachine.setState(new OutOfStockState());
vendingMachine.request();

return 0;

}

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();
}

}

Python

from abc import ABC, abstractmethod

class VendingMachineState(ABC): @abstractmethod def handle_request(self): pass

class ReadyState(VendingMachineState): def handle_request(self): print("Ready state: Please select a product.")

class ProductSelectedState(VendingMachineState): def handle_request(self): print("Product selected state: Processing payment.")

class PaymentPendingState(VendingMachineState): def handle_request(self): print("Payment pending state: Dispensing product.")

class OutOfStockState(VendingMachineState): def handle_request(self): print("Out of stock state: Product unavailable. Please select another product.")

class VendingMachineContext: def init(self): self.state = None

def set_state(self, state):
    self.state = state

def request(self):
    self.state.handle_request()

def main(): # Create context vending_machine = VendingMachineContext()

# Set initial state
vending_machine.set_state(ReadyState())

# Request state change
vending_machine.request()

# Change state
vending_machine.set_state(ProductSelectedState())

# Request state change
vending_machine.request()

# Change state
vending_machine.set_state(PaymentPendingState())

# Request state change
vending_machine.request()

# Change state
vending_machine.set_state(OutOfStockState())

# Request state change
vending_machine.request()

if name == "main": main()

JavaScript

class VendingMachineState { handleRequest() { throw new Error('Method handleRequest must be implemented.'); } }

class ReadyState extends VendingMachineState { handleRequest() { console.log('Ready state: Please select a product.'); } }

class ProductSelectedState extends VendingMachineState { handleRequest() { console.log('Product selected state: Processing payment.'); } }

class PaymentPendingState extends VendingMachineState { handleRequest() { console.log('Payment pending state: Dispensing product.'); } }

class OutOfStockState extends VendingMachineState { handleRequest() { console.log('Out of stock state: Product unavailable. Please select another product.'); } }

class VendingMachineContext { constructor() { this.state = null; }

setState(state) {
    this.state = state;
}

request() {
    this.state.handleRequest();
}

}

function main() { // Create context const 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();

}

main();

`

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.

Advantages

This pattern makes state-dependent behavior easier to manage and extend.

Disadvantages

Despite its benefits, it has some drawbacks.