State pattern is used to change the behavior of an object when the state is changed. With the change in state, the behavior of that object is completely changed.
This article demonstrates State pattern implementations in Java. Check the following examples.
Examples
Here are a few examples of State pattern implementation in Java-
Example #1: Simplest State Pattern Implementation
Let’s consider the simplest example of State pattern.
State Abstract Class (The Interface for State Classes)
Abstract class for all state class common interface. This stores a reference to the context. The constructor accepts a context object and sets the context reference variable.
In the constructor call the context function to set state, and pass the current object.
// State.java
package com.bigboxcode.designpattern.state.state;
public abstract class State {
protected Context context;
public State(Context context) {
this.context = context;
this.context.setState(this);
}
public abstract void actionOne();
public abstract void actionTwo();
}
Concrete State One Class
Concrete state class that extends the State abstract class. Calls parent constructor and passes the content object.
// ConcreteStateOne.java
package com.bigboxcode.designpattern.state.state;
public class ConcreteStateOne extends State {
public ConcreteStateOne(Context context) {
super(context);
}
@Override
public void actionOne() {
System.out.println("Calling 'actionOne' of - 'ConcreteStateOne'");
}
@Override
public void actionTwo() {
System.out.println("Calling 'actionTwo' of - 'ConcreteStateOne'");
}
}
Concrete State Two Class
Another concrete state class that extends the State abstract class.
// ConcreteStateTwo.java
package com.bigboxcode.designpattern.state.state;
public class ConcreteStateTwo extends State {
public ConcreteStateTwo(Context context) {
super(context);
}
@Override
public void actionOne() {
System.out.println("Calling 'actionOne' of - 'ConcreteStateTwo'");
}
@Override
public void actionTwo() {
System.out.println("Calling 'actionTwo' of - 'ConcreteStateTwo'");
}
}
Context Class
In the context class, we can set the state here and when any operation is performed, it calls the operation from the state class.
// Context.java
package com.bigboxcode.designpattern.state.state;
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
public void performActionOne() {
this.state.actionOne();
}
public void performActionTwo() {
this.state.actionTwo();
}
}
Demo
Create a context object. Pass the context while creating a state object, this will call the setState of the context and sets the state as the passed object.
If we want to change the behavior of the context then we can create another state object and pass the same context.
Calling functions from the context, will call the functions from the relevant state object.
// Demo.java
package com.bigboxcode.designpattern.state.state;
public class Demo {
public static void main(String[] args) {
Context context = new Context();
new ConcreteStateOne(context);
context.performActionOne();
System.out.println("-------------------------------------------");
new ConcreteStateTwo(context);
context.performActionOne();
context.performActionTwo();
}
}
Output
Calling 'actionOne' of - 'ConcreteStateOne'
-------------------------------------------
Calling 'actionOne' of - 'ConcreteStateTwo'
Calling 'actionTwo' of - 'ConcreteStateTwo'
Example #2: Order State Change
Let’s consider another example that is a little complex. We are demonstrating an order processing state here.
Order State
// OrderState.java
package com.bigboxcode.designpattern.state.orderstate;
public abstract class OrderState {
protected OrderContext context;
public OrderState(OrderContext context) {
this.context = context;
this.context.setState(this);
}
public abstract void process();
}
Order Check State Class
// OrderCheckState.java
package com.bigboxcode.designpattern.state.orderstate;
public class OrderCheckState extends OrderState {
public OrderCheckState(OrderContext context) {
super(context);
}
@Override
public void process() {
// Write code to process the order
System.out.println("Checking the order validity and other information");
context.setState(context.getOrderInProgressState());
}
}
Order In-Progress State Class
// OrderInProgressState.java
package com.bigboxcode.designpattern.state.orderstate;
public class OrderInProgressState extends OrderState {
public OrderInProgressState(OrderContext context) {
super(context);
}
@Override
public void process() {
// Write code to process the order
System.out.println("Processing the order");
context.setState(context.getOrderDeliverState());
}
}
Order Deliver State Class
// OrderDeliverState.java
package com.bigboxcode.designpattern.state.orderstate;
public class OrderDeliverState extends OrderState {
public OrderDeliverState(OrderContext context) {
super(context);
}
@Override
public void process() {
// Write code to process the order
System.out.println("Delivering the order");
context.setState(context.getOrderReceiveState());
}
}
Order Receive State Class
// OrderReceiveState.java
package com.bigboxcode.designpattern.state.orderstate;
public class OrderReceiveState extends OrderState {
public OrderReceiveState(OrderContext context) {
super(context);
}
@Override
public void process() {
// Write code to process the order
System.out.println("Order received");
context.setState(null);
}
}
Order Context Class
// OrderContext.java
package com.bigboxcode.designpattern.state.orderstate;
public class OrderContext {
private OrderState state;
private OrderState orderCheckState;
private OrderState orderInProgressState;
private OrderState orderDeliverState;
private OrderState orderReceiveState;
public OrderContext() {
orderCheckState = new OrderCheckState(this);
orderInProgressState = new OrderInProgressState(this);
orderDeliverState = new OrderDeliverState(this);
orderReceiveState = new OrderReceiveState(this);
// Set the placed state as default
state = orderCheckState;
}
public void setState(OrderState state) {
this.state = state;
}
public OrderState getState() {
return state;
}
public OrderState getOrderCheckState() {
return orderCheckState;
}
public OrderState getOrderInProgressState() {
return orderInProgressState;
}
public OrderState getOrderDeliverState() {
return orderDeliverState;
}
public OrderState getOrderReceiveState() {
return orderReceiveState;
}
public void runNextProcess() {
if (state != null) {
state.process();
} else {
System.out.println("Order processing complete");
}
}
}
Demo
// Demo.java
package com.bigboxcode.designpattern.state.orderstate;
public class Demo {
public static void main(String[] args) {
OrderContext order = new OrderContext();
order.runNextProcess();
order.runNextProcess();
order.runNextProcess();
order.runNextProcess();
// Trying to process after all steps are complete
order.runNextProcess();
}
}
Output
Checking the order validity and other information
Processing the order
Delivering the order
Order received
Order processing complete
Source Code
Use the following link to get the source code:
Example | Source Code Link |
---|---|
Example #1: Simplest State Pattern Implementation | GitHub |
Example #2: Order State Change | GitHub |
Other Code Implementations
Use the following links to check State pattern implementation in other programming languages.