DEV Community

NOOB
NOOB

Posted on

2 Vending Machine

package LLD.vendingmachine;

import java.util.HashMap;
import java.util.Map;

public class VendingMachineSystem {

class Product {
    String code;
    String name;
    double price;
    int quantity;

    Product(String code, String name, double price, int quantity) {
        this.code = code;
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }
}

interface VendingState {
    void select(VendingMachine machine, String code);
    void insert(VendingMachine machine, double amount);
    void dispense(VendingMachine machine);
    void cancel(VendingMachine machine);
}

class IdleState implements VendingState {

    @Override
    public void select(VendingMachine machine, String code) {
        Product product = machine.products.get(code);

        if (product == null || product.quantity == 0) {
            throw new IllegalStateException("Product unavailable");
        }

        machine.selected = product;
        machine.state = new SelectedState();
    }

    @Override
    public void insert(VendingMachine machine, double amount) {
        throw new IllegalStateException("Select Product first");
    }

    @Override
    public void dispense(VendingMachine machine) {
        throw new IllegalStateException("Select Product first");
    }

    @Override
    public void cancel(VendingMachine machine) {
        throw new IllegalStateException("No transaction");
    }
}

class SelectedState implements VendingState {

    @Override
    public void select(VendingMachine machine, String code) {
        throw new IllegalStateException("Product already selected");
    }

    @Override
    public void insert(VendingMachine machine, double amount) {
        machine.money += amount;
        if (machine.money >= machine.selected.price) {
            machine.state = new DispensingState();
        }
    }

    @Override
    public void dispense(VendingMachine machine) {
        throw new IllegalStateException("Insufficient money");
    }

    @Override
    public void cancel(VendingMachine machine) {
        System.out.println("Transaction cancelled. Returning: $" + machine.money);
        machine.reset();
    }
}

class DispensingState implements VendingState {

    @Override
    public void select(VendingMachine machine, String code) {
        throw new IllegalStateException("Transaction in progress");
    }

    @Override
    public void insert(VendingMachine machine, double amount) {
        throw new IllegalStateException("Payment complete");
    }

    @Override
    public void dispense(VendingMachine machine) {
        machine.selected.quantity--;

        double change = machine.money - machine.selected.price;

        System.out.println("Dispensing " + machine.selected.name);
        System.out.println("Change: $" + change);
        machine.reset();
    }

    @Override
    public void cancel(VendingMachine machine) {
        System.out.println("Too late to cancel, dispensing in progress.");
        machine.reset();
    }
}

class VendingMachine {
    Map<String, Product> products = new HashMap<>();
    VendingState state = new IdleState();

    Product selected;
    double money;

    void select(String code) {
        state.select(this, code);
    }

    void insert(double amount) {
        state.insert(this, amount);
    }

    void dispense() {
        state.dispense(this);
    }

    void cancel() {
        state.cancel(this);
    }

    void reset() {
        selected = null;
        money = 0;
        state = new IdleState();
    }
}

public static void main(String[] args) {
    // 1. Initialize the system
    VendingMachineSystem system = new VendingMachineSystem();
    VendingMachine machine = system.new VendingMachine();

    // 2. Load products into the machine
    machine.products.put("A1", system.new Product("A1", "Coke", 1.50, 5));
    machine.products.put("B2", system.new Product("B2", "Chips", 2.00, 3));
    machine.products.put("C3", system.new Product("C3", "Water", 1.00, 0)); // Out of stock

    System.out.println("Vending Machine Setup Complete.\n");

    try {
        // Test Case 1: Successful Purchase with Exact Change
        System.out.println("--- Test 1: Buying Chips ---");
        machine.select("B2");
        System.out.println("Selected Chips. Price: $2.00");
        machine.insert(2.00);
        machine.dispense();

        // Test Case 2: Successful Purchase with Overpayment
        System.out.println("\n--- Test 2: Buying Coke (with extra money) ---");
        machine.select("A1");
        System.out.println("Selected Coke. Price: $1.50");
        machine.insert(1.00);
        machine.insert(1.00); // Total $2.00, triggers DispensingState
        machine.dispense();   // Should return $0.50 change

        // Test Case 3: Cancelling a transaction
        System.out.println("\n--- Test 3: Cancelling Transaction ---");
        machine.select("A1");
        System.out.println("Selected Coke. Price: $1.50");
        machine.insert(1.00);
        machine.cancel();

        // Test Case 4: Trying to buy out of stock item
        System.out.println("\n--- Test 4: Buying Out of Stock Item ---");
        machine.select("C3"); // Should throw an exception

    } catch (Exception e) {
        System.out.println("Error: " + e.getMessage());
    }
}
Enter fullscreen mode Exit fullscreen mode

}

Top comments (0)