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.

Check complete details and explanations about State pattern in the article: State Design Pattern

This article demonstrates State pattern implementations in Java. Check the following examples.

Example #1: Simplest State Pattern Implementation

Let’s consider the simplest example of State pattern.

State Abstract Class (The Interface for State Classes)

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

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

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

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

// 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:

Leave a Comment