Introduction
In this post, we will create a fully functional vending machine in Java that simulates the purchasing process. The vending machine allows users to select items, insert coins, and dispense selected items if enough money is inserted. It also handles refunds, manages item and coin inventories, and calculates the appropriate change if excess coins are inserted.
This vending machine follows object-oriented principles, making the code reusable and modular.
Problem Statement
We need to design a vending machine in Java that:
- Displays a set of items and their prices.
- Accepts coins and tracks the balance.
- Dispenses an item if enough coins are inserted.
- Returns change if more money is inserted than needed.
- Allows users to request a refund before purchasing an item.
- Alerts when an item is out of stock or if there isn’t enough money.
- Tracks item and coin inventories.
Example:
- Input: Select item
TWIX
, insert50
(price: 35) - Output: Dispense
TWIX
, return15
as change.
Vending Machine Design
Components:
Coin
Enum: Represents the different coin denominations.Item
Enum: Represents the items available in the vending machine.Inventory
Class: Manages the stock levels of coins and items.Selector
Interface: Defines the core functions of the vending machine, such as selecting an item, inserting coins, purchasing, and requesting refunds.VendingMachine
Class: Implements theSelector
interface, handling the main logic, such as managing coins, items, transactions, and dispensing change.Main
Class: The driver class to demonstrate the functionality of the vending machine.
Vending Machine Implementation in Java
1. Coin Enum
Coin
enum defines the accepted coin denominations: PENNY
, NICKEL
, DIME
, and QUARTER
.public enum Coin {
PENNY(1), NICKEL(5), DIME(10), QUARTER(25);
private final int denomination;
Coin(int denomination) {
this.denomination = denomination;
}
public int getDenomination() {
return denomination;
}
}
2. Item Enum
Item
enum defines the available items in the vending machine along with their prices.public enum Item {
SKITTLES("Skittles", 15), TWIX("Twix", 35), SNICKERS("Snickers", 25);
private final String name;
private final int price;
Item(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
3. Inventory Class
import java.util.HashMap;
import java.util.Map;
public final class Inventory<T> {
private Map<T, Integer> inventory = new HashMap<>();
public int getQuantity(T item) {
return inventory.getOrDefault(item, 0);
}
public void add(T item, int quantity) {
int count = inventory.getOrDefault(item, 0);
inventory.put(item, count + quantity);
}
public void deduct(T item) {
if (hasItem(item)) {
int count = inventory.get(item);
inventory.put(item, count - 1);
}
}
public boolean hasItem(T item) {
return getQuantity(item) > 0;
}
public void clear() {
inventory.clear();
}
}
4. Selector Interface
- The
Selector
interface defines the core methods for the vending machine, such as selecting an item, inserting coins, purchasing an item, and requesting a refund.
import java.util.List;
import java.util.Map;
public interface Selector {
void selectItem(Item item);
int checkPrice(Item item);
void insertCoin(Coin coin);
Map<Item, List<Coin>> purchaseItem();
List<Coin> refund();
void reset();
}
5. Vending Machine Class
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class VendingMachine implements Selector {
private Inventory<Coin> coinInventory = new Inventory<>();
private Inventory<Item> itemInventory = new Inventory<>();
private int currentBalance;
private Item currentItem;
public VendingMachine() {
initializeMachine();
}
// Initialize the vending machine with items and coins
private void initializeMachine() {
for (Coin coin : Coin.values()) {
coinInventory.add(coin, 10); // Adding 10 coins of each type
}
for (Item item : Item.values()) {
itemInventory.add(item, 5); // Adding 5 of each item
}
}
@Override
public void selectItem(Item item) {
if (itemInventory.hasItem(item)) {
currentItem = item;
System.out.println("Selected item: " + item.getName());
} else {
System.out.println("Item is out of stock.");
}
}
@Override
public int checkPrice(Item item) {
return item.getPrice();
}
@Override
public void insertCoin(Coin coin) {
currentBalance += coin.getDenomination();
coinInventory.add(coin, 1);
System.out.println("Inserted " + coin + ". Current balance: " + currentBalance);
}
@Override
public Map<Item, List<Coin>> purchaseItem() {
if (currentItem == null) {
throw new IllegalStateException("No item selected.");
}
if (currentBalance >= currentItem.getPrice()) {
int changeAmount = currentBalance - currentItem.getPrice();
List<Coin> change = getChange(changeAmount);
itemInventory.deduct(currentItem);
currentBalance = 0;
System.out.println("Dispensing " + currentItem.getName());
return Collections.singletonMap(currentItem, change);
} else {
throw new IllegalStateException("Insufficient balance.");
}
}
@Override
public List<Coin> refund() {
List<Coin> refund = getChange(currentBalance);
currentBalance = 0;
return refund;
}
@Override
public void reset() {
itemInventory.clear();
coinInventory.clear();
currentBalance = 0;
initializeMachine();
}
private List<Coin> getChange(int amount) {
List<Coin> change = new ArrayList<>();
while (amount > 0) {
if (amount >= Coin.QUARTER.getDenomination() && coinInventory.hasItem(Coin.QUARTER)) {
change.add(Coin.QUARTER);
amount -= Coin.QUARTER.getDenomination();
} else if (amount >= Coin.DIME.getDenomination() && coinInventory.hasItem(Coin.DIME)) {
change.add(Coin.DIME);
amount -= Coin.DIME.getDenomination();
} else if (amount >= Coin.NICKEL.getDenomination() && coinInventory.hasItem(Coin.NICKEL)) {
change.add(Coin.NICKEL);
amount -= Coin.NICKEL.getDenomination();
} else if (amount >= Coin.PENNY.getDenomination() && coinInventory.hasItem(Coin.PENNY)) {
change.add(Coin.PENNY);
amount -= Coin.PENNY.getDenomination();
} else {
throw new IllegalStateException("Insufficient change available.");
}
}
return change;
}
}
6. Main Class
Main
class demonstrates the usage of the vending machine, including selecting an item, inserting coins, purchasing, and refunding.public class Main {
public static void main(String[] args) {
VendingMachine vm = new VendingMachine();
// Select item TWIX
vm.selectItem(Item.TWIX);
// Insert coins
vm.insertCoin(Coin.QUARTER); // 25
vm.insertCoin(Coin.QUARTER); // 25, total 50
// Purchase item
vm.purchaseItem();
// Example of refund (if no purchase was made)
List<Coin> refund = vm.refund();
System.out.println("Refunded coins: " + refund);
}
}
Output:
Selected item: Twix
Inserted QUARTER. Current balance: 25
Inserted QUARTER. Current balance: 50
Dispensing Twix
Conclusion
This complete Java vending machine simulates a real-world vending machine. The code manages coins and items, handles transactions, and ensures that the correct change is returned to the user. The design follows object-oriented principles, making it easy to extend and maintain.
Comments
Post a Comment
Leave Comment