State Pattern
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 74 of 87.
The State Pattern is a behavioral design pattern that allows an object to change its behavior when its internal state changes. The object appears to change its class, but in reality, it delegates behavior to different state objects. Think of a vending machine: its response to pressing a button depends on whether it's idle, has money inserted, or is dispensing a product.
Instead of using complex conditional statements to handle different states, you encapsulate each state in its own class. The pattern involves a Context that maintains a reference to the current state, and State classes that define behavior for each state:
interface State {
void handle(Context context);
}
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}Each concrete state implements the behavior and can trigger transitions to other states:
class IdleState implements State {
public void handle(Context context) {
System.out.println("Idle: Insert coin to start");
context.setState(new ActiveState());
}
}
class ActiveState implements State {
public void handle(Context context) {
System.out.println("Active: Processing...");
context.setState(new IdleState());
}
}The context delegates requests to its current state, and the behavior changes automatically as the state changes:
Context context = new Context();
context.setState(new IdleState());
context.request(); // Idle: Insert coin to start
context.request(); // Active: Processing...The State Pattern is ideal when an object's behavior depends heavily on its state and must change at runtime. It eliminates large conditional blocks and makes adding new states straightforward—just create a new class implementing the State interface.
Challenge
EasyLet's build a document workflow system using the State Pattern! You'll create a system that models how a document moves through different stages—Draft, Review, and Published—with each state determining what actions are available and how the document behaves when you try to edit or approve it.
You'll organize your code across four files:
DocumentState.java: Define theDocumentStateinterface that all states will implement. It should declare two methods:edit(Document doc)for attempting to edit the document, andapprove(Document doc)for attempting to approve/advance the document to the next stage.States.java: Create three concrete state classes that implementDocumentState:DraftState- Wheneditis called, printEditing draft.... Whenapproveis called, printDraft approved. Moving to review.and transition the document toReviewState.ReviewState- Wheneditis called, printCannot edit during review.(no state change). Whenapproveis called, printReview complete. Publishing document.and transition toPublishedState.PublishedState- Wheneditis called, printCannot edit published document.. Whenapproveis called, printDocument already published.. Neither action changes the state.Document.java: Create the context class that maintains the current state. YourDocumentshould have:A private field holding the current
DocumentState, initialized toDraftStatein the constructor.A
setState(DocumentState state)method that changes the current state.An
edit()method that delegates to the current state'seditmethod.An
approve()method that delegates to the current state'sapprovemethod.A
getStatus()method that returns the simple class name of the current state (usegetClass().getSimpleName()).Main.java: Demonstrate your state system! You'll receive one input: a sequence of actions as a comma-separated string where each action is eithereditorapprove(for example:edit,approve,edit,approve).Create a
Documentand print its initial status in the formatStatus: [state]. Then process each action in order, calling the appropriate method on the document. After each action, print the current status.
You will receive one input: a comma-separated string of actions.
For example, with input edit,approve,approve, your output would be:
Status: DraftState
Editing draft...
Status: DraftState
Draft approved. Moving to review.
Status: ReviewState
Review complete. Publishing document.
Status: PublishedStateNotice how the same approve() call produces different results depending on the document's current state—this is the essence of the State Pattern! The document doesn't use conditionals to check its state; instead, it delegates behavior to the current state object, which handles the action appropriately and triggers transitions when needed.
Cheat sheet
The State Pattern is a behavioral design pattern that allows an object to change its behavior when its internal state changes by delegating behavior to different state objects instead of using complex conditional statements.
The pattern consists of a Context that maintains a reference to the current state, and State classes that define behavior for each state:
interface State {
void handle(Context context);
}
class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}Each concrete state implements the behavior and can trigger transitions to other states:
class IdleState implements State {
public void handle(Context context) {
System.out.println("Idle: Insert coin to start");
context.setState(new ActiveState());
}
}
class ActiveState implements State {
public void handle(Context context) {
System.out.println("Active: Processing...");
context.setState(new IdleState());
}
}The context delegates requests to its current state, and behavior changes automatically as the state changes:
Context context = new Context();
context.setState(new IdleState());
context.request(); // Idle: Insert coin to start
context.request(); // Active: Processing...The State Pattern is ideal when an object's behavior depends heavily on its state and must change at runtime. It eliminates large conditional blocks and makes adding new states straightforward.
Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Create a new Document
// TODO: Print the initial status in format "Status: [state]"
// TODO: Split the input by comma to get individual actions
// TODO: Loop through each action
// - If action is "edit", call edit() on document
// - If action is "approve", call approve() on document
// - After each action, print the current status
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System9Generics
Introduction to GenericsGeneric ClassesGeneric MethodsBounded Type ParametersWildcards (?, extends, super)Recap - Generic Container12Design Patterns Part 2
Command PatternAdapter PatternDecorator PatternTemplate Method PatternState PatternComposite PatternIterator Pattern