Design Pattern: State Pattern in Java

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:

Other Code Implementations

Use the following links to check State pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.