0% found this document useful (0 votes)
3 views12 pages

State Pattern

The document explains the State Design Pattern using real-life examples of a Traffic Signal and a Vending Machine. It details the implementation of the pattern through UML diagrams and code, illustrating how objects can change their behavior based on their internal state. The document also includes specific classes and methods for managing states in a Vending Machine, such as IdleState, HasMoneyState, SelectionState, and DispenseState.

Uploaded by

Ali Arsalaan
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views12 pages

State Pattern

The document explains the State Design Pattern using real-life examples of a Traffic Signal and a Vending Machine. It details the implementation of the pattern through UML diagrams and code, illustrating how objects can change their behavior based on their internal state. The document also includes specific classes and methods for managing states in a Vending Machine, such as IdleState, HasMoneyState, SelectionState, and DispenseState.

Uploaded by

Ali Arsalaan
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Vending Machine Using State Pattern Pattern

Definition
Real Life Example: Traffic Signal
State Design Pattern UML:
Lets Code this UML for Traffic Signal:
Real Life Example: Vending Machine
Understanding the working of a Vending Machine
Different States and Operations
Example: Vending Machine
Vending Machine representation using State Pattern
Implementation(e.g., Vending Machine)

Resources

Video → 41. All Behavioral Design Patterns | Strategy, Observer, St


ate, Template, Command, Visitor, Memento
Video → 16. Design Vending Machine (Hindi) | LLD of Vending Mac
hine | State Design Pattern | LLD question

Definition
The State Pattern allows an object to change its behavior dynamically at runtime whenever
there is a change in its internal state.

Real Life Example: Traffic Signal


This type of problems, where Object change the state after performing certain operation can be solved through : State
Design Pattern

State Design Pattern UML:

Lets Code this UML for Traffic Signal:

1 public interface TrafficLightState {


2 void action(TrafficLight signal);
3 }
4

1 public class RedState implements TrafficLightState {


2
3 @Override
4 public void action(TrafficLight signal) {
5 //STOP behavior
6 [Link](new GreenState()); // next state
7 }
8 }
9
10
11 public class GreenState implements TrafficLightState {
12
13 @Override
14 public void action(TrafficLight signal) {
15 //GO behavior
16 [Link](new YellowState()); // next state
17 }
18 }
19
20
21 public class YellowState implements TrafficLightState {
22
23 @Override
24 public void action(TrafficLight signal) {
25 //Slow Down behavior
26 [Link](new RedState()); // next state
27 }
28 }
29
30

1 public class TrafficLight {


2 private TrafficLightState state;
3
4 public TrafficLight() {
5 [Link] = new RedState(); // initial state
6 }
7
8 public void setState(TrafficLightState state) {
9 [Link] = state;
10 }
11
12 public void change() {
13 [Link](this);
14 }
15 }
16

1 public class Main {


2 public static void main(String[] args) {
3 TrafficLight trafficLight = new TrafficLight (); //initial
signal state is RED
4
5 [Link](); // RED → GREEN
6 [Link](); // GREEN → YELLOW
7 [Link](); // YELLOW → RED
8 }
9 }
10
Real Life Example: Vending Machine

Understanding the working of a Vending Machine

Different States and Operations


Example: Vending Machine

State Operations
IdleState Press Insert Coin button
HasMoney State Insert Coin
Select Product
Cancel / Refund
Selection State Choose Product
Return change
Cancel/Refund full amount
Dispense Product State Dispense Product

Vending Machine representation using State Pattern

1. State Interface(e.g., VendingMachineState ): Declares common functions that all states must implement.
2. Concrete States(e.g., IdleState , SelectionState , hasMoney , DispenseState ): Each class
implements the state interface behaviors(operations) differently depending on the current state of the vending
machine, and an exception is thrown for operations that do not apply to the current state.
3. Context Class (e.g., VendingMachine ): Maintains a reference to the current state. Holds all possible states as
objects. Delegates call to the current state object.
4. Client( VendingMachineAppDemo ): Interacts with Context Class ( VendingMachine ) and expects
appropriate behavior as per changes in the state of the object.

Implementation(e.g., Vending Machine)


1 public abstract class State {
2
3 public void clickOnInsertCoinButton(VendingMachine machine) throws
Exception {
4 // by default nothing happens
5 }
6
7 public void clickOnStartProductSelectionButton(VendingMachine
machine) throws Exception {
8 // by default nothing happens
9 }
10
11 public void insertCoin(VendingMachine machine, Coin coin) throws
Exception {
12 // by default nothing happens
13 }
14
15 public void chooseProduct(VendingMachine machine, int codeNumber)
throws Exception {
16 // by default nothing happens
17 }
18
19 public int getChange(int returnChangeMoney) throws Exception {
20 // by default nothing happens
21 return 0;
22 }
23
24 public Item dispenseProduct(VendingMachine machine, int
codeNumber) throws Exception {
25 // by default nothing happens
26 return null;
27 }
28
29 public List<Coin> refundFullMoney(VendingMachine machine) throws
Exception {
30 // by default nothing happens
31 return null;
32 }
33
34 public void updateInventory(VendingMachine machine, Item item, int
codeNumber) throws Exception {
35 // by default nothing happens
36 }
37 }

1 public class IdleState extends State {


2
3 public IdleState(){
4 [Link]("Currently Vending machine is in
IdleState");
5 }
6
7 public IdleState(VendingMachine machine){
8 [Link]("Currently Vending machine is in
IdleState");
9 [Link](new ArrayList<>());
10 }
11
12 @Override
13 public void clickOnInsertCoinButton(VendingMachine machine) throws
Exception{
14 [Link](new HasMoneyState());
15 }
16
17 @Override
18 public void updateInventory(VendingMachine machine, Item item, int
codeNumber) throws Exception {
19 [Link]().addItem(item, codeNumber);
20 }
21 }

1 public class HasMoneyState extends State {


2
3 public HasMoneyState(){
4 [Link]("Currently Vending machine is in
HasMoneyState");
5 }
6
7 @Override
8 public void clickOnStartProductSelectionButton(VendingMachine
machine) throws Exception {
9 [Link](new SelectionState());
10 }
11
12 @Override
13 public void insertCoin(VendingMachine machine, Coin coin) throws
Exception {
14 [Link]("Accepted the coin");
15 [Link]().add(coin);
16 }
17
18 @Override
19 public List<Coin> refundFullMoney(VendingMachine machine) throws
Exception {
20 [Link]("Returned the full amount back in the Coin
Dispense Tray");
21 [Link](new IdleState(machine));
22 return [Link]();
23 }
24 }

1 public class SelectionState extends State {


2
3 public SelectionState(){
4 [Link]("Currently Vending machine is in
SelectionState");
5 }
6
7 @Override
8 public void chooseProduct(VendingMachine machine, int codeNumber)
throws Exception{
9
10 //1. get item of this codeNumber
11 Item item = [Link]().getItem(codeNumber);
12
13 //2. total amount paid by User
14 int paidByUser = 0;
15 for(Coin coin : [Link]()){
16 paidByUser = paidByUser + [Link];
17 }
18
19 //3. compare product price and amount paid by user
20 if(paidByUser < [Link]()) {
21 [Link]("Insufficient Amount, Product you
selected is for price: " + [Link]() + " and you paid: " +
paidByUser);
22 refundFullMoney(machine);
23 throw new Exception("insufficient amount");
24 }
25 else if(paidByUser >= [Link]()) {
26
27 if(paidByUser > [Link]()) {
28 getChange([Link]());
29 }
30 [Link](new DispenseState(machine,
codeNumber));
31 }
32 }
33
34 @Override
35 public int getChange(int returnExtraMoney) throws Exception{
36 //actual logic should be to return COINs in the dispense tray,
but for simplicity i am just returning the amount to be refunded
37 [Link]("Returned the change in the Coin Dispense
Tray: " + returnExtraMoney);
38 return returnExtraMoney;
39 }
40
41 @Override
42 public List<Coin> refundFullMoney(VendingMachine machine) throws
Exception{
43 [Link]("Returned the full amount back in the Coin
Dispense Tray");
44 [Link](new IdleState(machine));
45 return [Link]();
46 }
47 }

1 public class DispenseState extends State {


2
3 DispenseState(VendingMachine machine, int codeNumber) throws
Exception{
4 [Link]("Currently Vending machine is in
DispenseState");
5 dispenseProduct(machine, codeNumber);
6 }
7
8 @Override
9 public Item dispenseProduct(VendingMachine machine, int
codeNumber) throws Exception{
10 [Link]("Product has been dispensed");
11 Item item = [Link]().getItem(codeNumber);
12 [Link]().updateSoldOutItem(codeNumber);
13 [Link](new IdleState(machine));
14 return item;
15 }
16 }
17
18

1 public class VendingMachine {


2
3 private State vendingMachineState;
4 private Inventory inventory;
5 private List<Coin> coinList;
6
7 public VendingMachine(){
8 vendingMachineState = new IdleState();
9 inventory = new Inventory(10);
10 coinList = new ArrayList<>();
11 }
12
13 public State getVendingMachineState() {
14 return vendingMachineState;
15 }
16
17 public void setVendingMachineState(State vendingMachineState) {
18 [Link] = vendingMachineState;
19 }
20
21 public Inventory getInventory() {
22 return inventory;
23 }
24
25 public void setInventory(Inventory inventory) {
26 [Link] = inventory;
27 }
28
29 public List<Coin> getCoinList() {
30 return coinList;
31 }
32
33 public void setCoinList(List<Coin> coinList) {
34 [Link] = coinList;
35 }
36 }

1 public enum Coin {


2
3 PENNY(1),
4 NICKEL(5),
5 DIME(10),
6 QUARTER(25);
7
8 public int value;
9
10 Coin(int value) {
11 [Link] = value;
12 }
13 }
14

1 public class Inventory {


2
3 ItemShelf[] inventory = null;
4
5 Inventory(int itemCount) {
6 inventory = new ItemShelf[itemCount];
7 initialEmptyInventory();
8 }
9
10 public ItemShelf[] getInventory() {
11 return inventory;
12 }
13
14 public void setInventory(ItemShelf[] inventory) {
15 [Link] = inventory;
16 }
17
18 public void initialEmptyInventory() {
19 int startCode = 101;
20 for (int i = 0; i < [Link]; i++) {
21 ItemShelf space = new ItemShelf();
22 [Link](startCode);
23 [Link](true);
24 inventory[i]= space;
25 startCode++;
26 }
27 }
28
29 public void addItem(Item item, int codeNumber) throws Exception {
30
31 for (ItemShelf itemShelf : inventory) {
32 if ([Link] == codeNumber) {
33 if ([Link]()) {
34 [Link] = item;
35 [Link](false);
36 } else {
37 throw new Exception("already item is present, you
can not add item here");
38 }
39 }
40 }
41 }
42
43 public Item getItem(int codeNumber) throws Exception {
44
45 for (ItemShelf itemShelf : inventory) {
46 if ([Link] == codeNumber) {
47 if ([Link]()) {
48 throw new Exception("item already sold out");
49 } else {
50
51 return [Link];
52 }
53 }
54 }
55 throw new Exception("Invalid Code");
56 }
57
58 public void updateSoldOutItem(int codeNumber){
59 for (ItemShelf itemShelf : inventory) {
60 if ([Link] == codeNumber) {
61 [Link](true);
62 }
63 }
64 }
65 }

1 public class ItemShelf {


2
3 int code;
4 Item item;
5 boolean soldOut;
6
7 public int getCode() {
8 return code;
9 }
10
11 public void setCode(int code) {
12 [Link] = code;
13 }
14
15 public Item getItem() {
16 return item;
17 }
18
19 public void setItem(Item item) {
20 [Link] = item;
21 }
22
23 public boolean isSoldOut() {
24 return soldOut;
25 }
26
27 public void setSoldOut(boolean soldOut) {
28 [Link] = soldOut;
29 }
30 }

1 public class Item {


2 ItemType type;
3 int price;
4
5 public ItemType getType() {
6 return type;
7 }
8
9 public void setType(ItemType type) {
10 [Link] = type;
11 }
12
13 public int getPrice() {
14 return price;
15 }
16
17 public void setPrice(int price) {
18 [Link] = price;
19 }
20 }
21
22
23 public enum ItemType {
24
25 COKE,
26 PEPSI,
27 JUICE,
28 SODA;
29 }
30

1 public class VendingMachineAppDemo {


2
3 public static void main(String args[]){
4
5 VendingMachine vendingMachine = new VendingMachine();
6 try {
7
8 [Link]("|");
9 [Link]("filling up the inventory");
10 [Link]("|");
11
12 fillUpInventory(vendingMachine);
13 displayInventory(vendingMachine);
14
15 [Link]("|");
16 [Link]("clicking on InsertCoinButton");
17 [Link]("|");
18
19 State vendingState =
[Link]();
20 [Link](vendingMachine);
21
22 vendingState = [Link]();
23 [Link](vendingMachine, [Link]);
24 [Link](vendingMachine, [Link]);
25 // [Link](vendingMachine, [Link]);
26
27 [Link]("|");
28 [Link]("clicking on ProductSelectionButton");
29 [Link]("|");
30
[Link](vendingMachine);
31
32 vendingState = [Link]();
33 [Link](vendingMachine, 102);
34
35 displayInventory(vendingMachine);
36
37 }
38 catch (Exception e){
39 displayInventory(vendingMachine);
40 }
41
42
43 }
44
45 private static void fillUpInventory(VendingMachine vendingMachine)
{
46 ItemShelf[] slots =
[Link]().getInventory();
47 for (int i = 0; i < [Link]; i++) {
48 Item newItem = new Item();
49 if(i >=0 && i<3) {
50 [Link]([Link]);
51 [Link](12);
52 }else if(i >=3 && i<5){
53 [Link]([Link]);
54 [Link](9);
55 }else if(i >=5 && i<7){
56 [Link]([Link]);
57 [Link](13);
58 }else if(i >=7 && i<10){
59 [Link]([Link]);
60 [Link](7);
61 }
62 slots[i].setItem(newItem);
63 slots[i].setSoldOut(false);
64 }
65 }
66
67 private static void displayInventory(VendingMachine
vendingMachine){
68
69 ItemShelf[] slots =
[Link]().getInventory();
70 for (int i = 0; i < [Link]; i++) {
71
72 [Link]("CodeNumber: " + slots[i].getCode() +
73 " Item: " + slots[i].getItem().getType().name() +
74 " Price: " + slots[i].getItem().getPrice() +
75 " isAvailable: " + !slots[i].isSoldOut());
76 }
77 }
78
79 }

You might also like