State Design Pattern by Example

State pattern falls under the category of Behavioral patterns. State design pattern comes in picture when a system’s behavior is depends on its own state or some other resource’s state. If an implementation is depends on the states, we end up with snarl of conditional statement every where in code. A very neat approach to deal with such situation is to separate out every state’s behavior and use them where ever they are applicable.

The state pattern allows an object to alter its behavior when is internal state changes . The object is appeared to change its class.

State pattern is a way to implement the same.

Class Diagram :

image As above class diagram shows, System class holds state instance. As state of system changes , all handle request delegated to respective State’s concrete implementation.

Example : Have an example of Vending machine. Vending machine has following states

  1. No Coin Inserted
  2. Coin Inserted
  3. Dispensing
  4. Empty

Following diagram explain behavior of vending machine with different states as well as actions

image

Class Diagram :

image

Here is the Complete Code

VendingMachine.java

package statepattern;
import statepattern.exception.MachineWarning;
public class VendingMachine {
    State coninInsertedState = new CoinInsertedState(this);
    State emptyState = new EmptyState(this);
    State noCoinInsertedState = new NoCoinInsertedState(this);
    State dispensingState = new DispensingState(this);
    State machineState = null;
    int capacity = 0;
    public VendingMachine() {
        machineState = noCoinInsertedState;
    }
    public void reFill(int count) {
        capacity += count;
        machineState = noCoinInsertedState;
    }
    /**
     * Two Actions performed by MAchine   
     */
    public void insertCoin() throws MachineWarning {
        machineState.insertCoin();
    }
    
    public void pressButton() throws MachineWarning {
        machineState.pressButton();
        machineState.dispense();
        capacity--;
    }
    
    public boolean isEmpty(){
        if(capacity<=0)
            return true;
        else
            return false;
    }
    
    public void setMachineState(State machineState) {
        this.machineState = machineState;
    }
    public State getMachineState() {
        return machineState;
    }
    public void setConinInsertedState(State coninInsertedState) {
        this.coninInsertedState = coninInsertedState;
    }
    public State getConinInsertedState() {
        return coninInsertedState;
    }
    public void setEmptyState(State emptyState) {
        this.emptyState = emptyState;
    }
    public State getEmptyState() {
        return emptyState;
    }
    public void setNoCoinInsertedState(State noCoinInsertedState) {
        this.noCoinInsertedState = noCoinInsertedState;
    }
    public State getNoCoinInsertedState() {
        return noCoinInsertedState;
    }
    public void setDispensingState(State dispensingState) {
        this.dispensingState = dispensingState;
    }
    public State getDispensingState() {
        return dispensingState;
    }
    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }
    public int getCapacity() {
        return capacity;
    }
}


State interface



import statepattern.exception.MachineWarning;
public interface State {
   
    public void insertCoin()throws MachineWarning;
    public void pressButton()throws MachineWarning;
    public void dispense()throws MachineWarning;
}


Concrete States implementations



ConinINsertedState.java



package statepattern;
import statepattern.exception.MachineWarning;
public class CoinInsertedState implements State{
    VendingMachine machine =null;
    public CoinInsertedState(VendingMachine machine) {
        this.machine =  machine;
    }
    public void insertCoin() throws MachineWarning{
        throw new MachineWarning("Coin is already inserted.");
    }
    public void dispense() throws MachineWarning{
        throw new MachineWarning("Dispense button is not pressed.");
    
    }
    public void pressButton() throws MachineWarning{
        machine.setMachineState(machine.getDispensingState());
    }
}


DispensingState.java



package statepattern;
import statepattern.exception.MachineWarning;
public class DispensingState implements State{
    VendingMachine machine ;
    DispensingState(VendingMachine machine) {
        this.machine = machine;
    }
    public void insertCoin() throws MachineWarning {
        throw new MachineWarning("wait ... previous order is processing");
    }
    public void pressButton() throws MachineWarning {
        throw new MachineWarning("wait ... previous order is processing");
    }
    public void dispense() throws MachineWarning {
        machine.setMachineState(machine.getNoCoinInsertedState());
    }
}


EmptyState.java



package statepattern;
import statepattern.exception.MachineWarning;
public class EmptyState implements State{
    VendingMachine machine;
    public EmptyState(VendingMachine machine) {
        this.machine =  machine;
    }
    public void insertCoin() throws MachineWarning{
        throw new MachineWarning("Can not process the request");
    }
    public void pressButton() throws MachineWarning{
        throw new MachineWarning("Invalid Action");
    }
    public void dispense() throws MachineWarning{
        throw new MachineWarning("Invalid Action");
    }
}


NoCoinInsertedState.java


package statepattern;
import statepattern.exception.MachineWarning;
public class NoCoinInsertedState implements State{
    VendingMachine machine;
    public NoCoinInsertedState(VendingMachine machine) {
        this.machine =  machine;
    }
    public void insertCoin() throws MachineWarning{
        if (!machine.isEmpty()) {
            machine.setMachineState(machine.getConinInsertedState());
        }
        else {
            throw new MachineWarning("Can not process request .. Machine is out of stock");
        }
    }
    public void pressButton() throws MachineWarning{
        throw new MachineWarning("No coin inserted ..");
    }
    public void dispense() throws MachineWarning{
        throw new MachineWarning("Invalid Operation");
    }
}


I have run the Test class to check behavior of Vending MAchine in different states 


Test.java


package statepattern.test;
import statepattern.exception.MachineWarning;
import statepattern.VendingMachine;
public class Test {
    public Test() {
    }
    public static void main(String[] args) {
        VendingMachine machine = new VendingMachine();
        machine.reFill(2); // 
        //First despense 
        try {
            machine.insertCoin();
            machine.pressButton();
        } catch (MachineWarning e) {
            System.out.println("Test 1:" + e.getMessage());
        }
        //Second Test 
        try {
            machine.insertCoin();
            machine.insertCoin();
            machine.pressButton();
        } catch (MachineWarning e) {
            System.out.println("Test 2:" + e.getMessage());
            try {
                machine.pressButton();
            } catch (MachineWarning f) {
                // TODO
            }
        }
        //Test THree 
        try {
            machine.pressButton();
        } catch (MachineWarning e) {
            System.out.println("Test 3:" + e.getMessage());
        }
        //Test Four 
        try {
            machine.insertCoin();
        } catch (MachineWarning e) {
            System.out.println("Test 4:" + e.getMessage());
        }
    }
}


Output :


Test 2:Coin is already inserted.

Test 3:No coin inserted ..


Test 4:Can not process request .. Machine is out of stock



 

Comments

  1. Good post and thanks for those diagram it makes things pretty clear. By the way I have also blogged about 10 OOOPS and SOLID design principle for java developers let me know how do you find it.

    ReplyDelete
  2. Hi.

    Can you share the import statepattern.exception.MachineWarning class, please?

    ReplyDelete
  3. mcafee.com/activate registered trademarks, company names, product names and brand names are the property of their respective owners, and mcafee.com/activate disclaims any ownership in such third-party marks. The use of any third party trademarks, logos, or brand names is for informational purposes only, and does not imply an endorsement by mfmcafee.com or vice versa or that such trademark owner has authorized mfmcafee.com to promote its products or services.

    ReplyDelete


  4. office.com/setup is an independent support and service provider for the most secure remote technical services for all Office products. Our independent support services offer an instant support for all software related errors in the devices, laptops, desktops and peripherals. We have no link or affiliation with any of the brand or third-party company as we independently offer support service for all the product errors you face while using the Office. If your product is under warranty, then you may also avail our support services for free from manufacturer’s official website office.com/setup.

    ReplyDelete
  5. norton setup is an independent support and service provider for the most secure remote technical services for all norton products. Our independent support services offer an instant support for all software related errors in the devices, laptops, desktops and peripherals. We have no link or affiliation with any of the brand or third-party company as we independently offer support service for all the product errors you face while using the norton. If your product is under warranty, then you may also avail our support services for free from manufacturer’s official website norton.com/setup.

    ReplyDelete
  6. Thank You Author!!! You are sharing the very informative and great post. If anyone out there is looking to book Cheapest Kerala Tour Packages for Couple with Best Price then don’t go beyond Indian Travel Store – “Your Trusted Partner in your Travel Journey.”

    ReplyDelete
  7. What an amazing article is this. thanks for this, I really appreciate you.If you are interested in neo and gas wallets , please visit our websites to get full information about official neo wallets

    ReplyDelete
  8. Thanks in favor of sharing such a nice opinion, article is pleasant, thats why i have read it fully

    ReplyDelete
  9. Do you want to know about Marques Brownlee Net Worth, early life, career, biography, and relationship status?

    ReplyDelete

Post a Comment

Popular posts from this blog

Eclipse command framework core expression: Property tester

Composite Design Pattern by example