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 :
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
- No Coin Inserted
- Coin Inserted
- Dispensing
- Empty
Following diagram explain behavior of vending machine with different states as well as actions
Class Diagram :
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;elsereturn 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 despensetry {machine.insertCoin();machine.pressButton();} catch (MachineWarning e) {System.out.println("Test 1:" + e.getMessage());}//Second Testtry {machine.insertCoin();machine.insertCoin();machine.pressButton();} catch (MachineWarning e) {System.out.println("Test 2:" + e.getMessage());try {machine.pressButton();} catch (MachineWarning f) {// TODO}}//Test THreetry {machine.pressButton();} catch (MachineWarning e) {System.out.println("Test 3:" + e.getMessage());}//Test Fourtry {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
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.
ReplyDeleteThanks -:)
DeleteBoth are useful...great going guys...
ReplyDeleteHi.
ReplyDeleteCan you share the import statepattern.exception.MachineWarning class, please?
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
ReplyDeleteoffice.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.
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.
ReplyDeleteThank 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.”
ReplyDeleteWhat 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
ReplyDeleteThanks in favor of sharing such a nice opinion, article is pleasant, thats why i have read it fully
ReplyDeleteDo you want to know about Marques Brownlee Net Worth, early life, career, biography, and relationship status?
ReplyDelete