Finally all Steps to Design a Vending Machine in Java

Posted by Marta on February 2, 2023 Viewed 44795 times

Card image cap

In this article, you will learn how to design a vending machine in Java step by step. This vending machine is a simple text-based program, meaning you will interact with the vending machine using the console and entering text.

In this tutorial, you will see the full development process for a straightforward program. Learn more about the software development process here.

The first step is defining the requirements or defining how the vending machine java program should work. We will create use cases and UML diagrams to define and clarify these requirements.

Next, we will see how to create a skeleton implementation following an object-oriented programming approach. Creating a skeleton implementation means creating some classes and interfaces, but we won’t write all the code yet. This step will help to organize the code.

And finally, we will complete the implementation. While writing the code, I will recommend following the clean code rules shared in the following post: 4 Simple Tricks to Write Java Clean Code

Let’s get started!

1) Define the Vending Machine requirements

In this phase, we will refine how our Vending Machine java program will work using use cases and UML diagrams. Programming a Vending Machine is quite a vague statement. Therefore this step of the process is essential since it helps define how the program will work more concretely.

Let’s start by creating a use case:

  1. The vending machine displays a welcome message with all products and prices
  2. The vending machine asks the user to select a product
  3. The Vending machine asks the user to enter coins. The coins accepted are 5,10,20,50,100 cents
  4. The Vending machine calculates the total money inserted
  5. Calculate the change amount
  6. Calculate the minimum number of coins to return
  7. Display the change amount and coins to the user

Above you can see in bold some of the entities in this problem and highlighted the potential operations. Using these entities and operations, we can create a flow diagram that helps us to visualize how the entities will communicate:

2) Create a Skeleton Implementation

At this point, we have a much better understanding of how the application should work. Here are the classes:

  • Main
  • VendingMachineInterface
  • VendingMachineController
  • Calculator
  • Coin and CoinBundle
  • Product

The Main class will start the program and coordinate the communication between the user and the VendingMachineInterface.

import java.util.Scanner;

public class Main {

    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);

        // TODO To complete in step3
        VendingMachineInterface machineInterface = null;

        machineInterface.displayProducts();

        String selectedProduct = scanner.nextLine();
        machineInterface.selectProduct(Integer.parseInt(selectedProduct));

        machineInterface.displayEnterCoinsMessage();

        String userEnteredCoins = scanner.nextLine();
        int[] enteredCoins = {}; // TODO Complete in step 3
        machineInterface.enterCoins(enteredCoins);

        machineInterface.displayChangeMessage();

    }
}

The VendingMachineInterface is the class that defines how to communicate with the user. In this case, we will communicate using text through the console; therefore, the class will display text messages and receive user text input, like the product selected or the coins.

public interface VendingMachineInterface {

    void displayProducts();

    void selectProduct(int product);

    void displayEnterCoinsMessage();

    void enterCoins(int... coins);

    void displayChangeMessage();
}

Another important class is the Calculator. The calculator class will carry out operations to work out the total amount inserted and the minimum coins to return a change amount.

public interface Calculator {

    int calculateTotal(CoinBundle enteredCoins);
    CoinBundle calculateChange(int amountMoneyToReturn);

}

Next, we will create a VendingController class that coordinates the communication between the interface and the calculator. This class helps decouple the interface from the rest of the program. The interface doesn’t need to know how to calculate the change; it only needs to know where to request it.

public interface VendingMachineController {

    CoinBundle calculateChange(VendingMachineRequest request);
}
public class VendingMachineRequest {
    public Product product;
    public CoinBundle enteredCoins;

    public VendingMachineRequest(int selectedProduct, int... enteredCoins){
        // TODO Complete in step 3
        this.product = null;
        this.enteredCoins = new CoinBundle(enteredCoins);
    }
}

The Coin class will represent all coins accepted by the machine: 5 cents, 10 cents, 20 cents, 50 cents, and 100 cents.

public enum Coin {
    FIVE_CENTS(5), TEN_CENTS(10),  TWENTY_CENTS(20), FIFTY_CENTS(50), HUNDRED_CENTS(100);

    private int value

    Coin(int value){
        this.value = value;
    }

    public int getValue(){
        return this.value;
    }
}

Next, since we will receive a bunch of coins and return a bunch of coins, we could represent a class instead of passing around an array of numbers representing the number of coins. This change will make communication between classes simpler. We will call this class CoinBundle.

public class CoinBundle {
    public int number5CentsCoins;
    public int number10CentsCoins;
    public int number20CentsCoins;
    public int number50CentsCoins;
    public int number100CentsCoins;

    public CoinBundle(int... enteredCoins) {
        this.number5CentsCoins = enteredCoins[0];
        this.number10CentsCoins = enteredCoins[1];
        this.number20CentsCoins = enteredCoins[2];
        this.number50CentsCoins = enteredCoins[3];
        this.number100CentsCoins = enteredCoins[4];

    }
    
}

And finally, the Product class that will define the product that this vending machine offers. In this instance, our vending machine sells Twix chocolate bars, Coke, Water, and Sandwiches. This class has two pieces of information: the selection number to buy the product and the price.

public enum Product {
    TWIX(1,100), COKE(2,50), WATER(3,30), SANDWICH(4,150), EMPTY(0,0);

    private int selectionNumber;
    private int price;

    Product(int selectionNumber, int price){
        this.selectionNumber = selectionNumber;
        this.price = price;
    }

    public int getSelectionNumber(){
        return selectionNumber;
    }

    public int getPrice(){
        return this.price;
    }

}

So far, we have eight classes representing all entities in our program, and we have clearly defined each class’s responsibilities. What is left to do now is filling up the gap; in other words, implementing the interface with the real code.

3) Complete the implementation

Completing the implementation is the last step in our software development process. By now, we have a clear picture of how the program will look and how the code distributes across the different classes.

Since previously we defined some interfaces, now we will implement these interfaces. First, we will override these interfaces with concrete classes and methods that indicate to the program how to perform those interface operations.

3.1) Implement the VendingMachineInterface

Let’s start by implementing the VendingMachineInterface. The VendingMachineInterface is the class that will communicate with the user. Since it is a text-based interface, I will call it TextVendingMachineInterface. Consequently we need to write five methods:

  • displayProducts(): this method displays a message in the console welcoming the user and showing the available products.
  • selectProduct(int product): it receives the product selected by the user.
  • displayEnterCoinsMessage(): method that displays a message requesting the user to enter coins.
  • enterCoins(int... coins): it receives the coins entered by the user.
  • displayChangeMessage(): it displays a message letting the user know his change amount and coins.
public class TextVendingMachineInterface implements VendingMachineInterface {

    private VendingMachineController controller = new SimpleVendingMachineController();
    private int selectedProduct;
    private CoinBundle change;


    @Override
    public void displayProducts() {
        System.out.println(" *********************************************");
        System.out.println("     WELCOME TO THE VENDING MACHINE           ");
        System.out.println(" *********************************************");
        System.out.println("            Products available:               ");
        System.out.println("                                              ");
        for(Product product: Product.values()){
            if(!Product.EMPTY.equals(product)) {
                System.out.println("     " + product.getSelectionNumber() + "  " + product.name() + " - Price: " + product.getPrice() + "   ");
            }
        }
        System.out.println("                                              ");
        System.out.println(" Please select your product: ");


    }

    @Override
    public void selectProduct(int product) {
        this.selectedProduct = product;
    }

    @Override
    public void displayEnterCoinsMessage() {
        System.out.println(" Please enter coins as follows: ");
        System.out.println(" num of 5 cents coins,num of 10 cents coins,num of 20 cents coins,num of 50 cents coins,num of 100 cents coins  ");
        System.out.println("                                              ");
        System.out.println(" Example: If you would like to enter 2 ten cents coins: 0,2,0,0,0");
        System.out.println("Plese enter coins:");

    }

    @Override
    public void enterCoins(int... coins) {
        VendingMachineRequest request = new VendingMachineRequest(selectedProduct, coins);
        change = controller.calculateChange(request);

    }

    @Override
    public void displayChangeMessage() {
        System.out.println("                                              ");
        System.out.println("Your change is :"+ change.getTotal()+"cents splitted as follows: ");
        System.out.println("    100 cents coins: "+ change.number100CentsCoins);
        System.out.println("    50 cents coins: "+ change.number50CentsCoins);
        System.out.println("    20 cents coins: "+ change.number20CentsCoins);
        System.out.println("    10 cents coins: "+ change.number10CentsCoins);
        System.out.println("    5 cents coins: "+ change.number5CentsCoins);

    }
}

Also, add this method to the CoinBundle for the above code to work:

  public int getTotal(){
        int total = 0;
        total = total+this.number5CentsCoins*Coin.FIVE_CENTS.getValue();
        total = total+this.number10CentsCoins*Coin.TEN_CENTS.getValue();
        total = total+this.number20CentsCoins*Coin.TWENTY_CENTS.getValue();
        total = total+this.number50CentsCoins*Coin.FIFTY_CENTS.getValue();
        total = total+this.number100CentsCoins*Coin.HUNDRED_CENTS.getValue();
        return total;
    }

Also, you will need to update the VendingMachineRequest class and modify the constructor as follows:

 public VendingMachineRequest(int selectedProduct,int... enteredCoins){
	this.product = Product.valueOf(selectedProduct);
    this.enteredCoins = new CoinBundle(enteredCoins);
}

And add a .valueOf() method to the Product class. This method will map a number inserted by the user with an available product.

    public static Product valueOf(int numberSelection){
        for(Product product: Product.values()){
            if(numberSelection == product.getSelectionNumber()){
                return product;
            }
        }
        return EMPTY;
    }

3.2) Implement the VendingMachineController

Next, we will implement the VendingMachineController interface by creating a class called SimpleVendingMachineController. This class is merely coordinating communication between the previous interface and the calculator.

public class SimpleVendingMachineController implements VendingMachineController {

    private Calculator calculator = new SimpleCalculator();

    @Override
    public CoinBundle calculateChange(VendingMachineRequest request) {
        int total = calculator.calculateTotal(request.enteredCoins);
        int totalChange = total - request.product.getPrice();
        return calculator.calculateChange(totalChange);
    }
}

3.3) Implement the Calculator

Next is the calculator which is the class that calculates the total amount inserted by the user. Furthermore it calculates the number of coins the user should receive. Therefore we will create a class called SimpleCalculator, which will implement the Calculator interface.

public class SimpleCalculator implements Calculator{

    @Override
    public int calculateTotal(CoinBundle enteredCoins) {
        return enteredCoins.getTotal();
    }

    @Override
    public CoinBundle calculateChange(int amountMoneyToReturn) {
        CoinBundle change = new CoinBundle(new int[5]);
        int remainingAmount = amountMoneyToReturn;
        change.number100CentsCoins = remainingAmount / Coin.HUNDRED_CENTS.getValue();
        remainingAmount = remainingAmount % Coin.HUNDRED_CENTS.getValue();

        change.number50CentsCoins = remainingAmount / Coin.FIFTY_CENTS.getValue();
        remainingAmount = remainingAmount % Coin.FIFTY_CENTS.getValue();

        change.number20CentsCoins = remainingAmount / Coin.TWENTY_CENTS.getValue();
        remainingAmount = remainingAmount % Coin.TWENTY_CENTS.getValue();

        change.number10CentsCoins = remainingAmount / Coin.TEN_CENTS.getValue();
        remainingAmount = remainingAmount % Coin.TEN_CENTS.getValue();

        change.number5CentsCoins = remainingAmount / Coin.FIVE_CENTS.getValue();


        return change;
    }
}

3.4) Complete the Main class

And finally, there is one small detail that we need to modify in the Main class to complete the program implementation. After receiving the coins from the user as a String, we will need to convert them to an array of numbers. As a result, we will make the following change to the Main class:

	String userEnteredCoins = scanner.nextLine();
	// this was : int[] enteredCoins = {}
    int[] enteredCoins = Coin.parseCoins(userEnteredCoins);
    machineInterface.enterCoins(enteredCoins);

And add the parseCoins() method to the Coin class:

    public static int[] parseCoins(String coins){
        String[] numberCoinsInText = coins.split(",");
        int[] result = new int[numberCoinsInText.length];
        for(int index=0;index<numberCoinsInText.length;index++){
            result[index] = Integer.parseInt(numberCoinsInText[index]);
        }
        return result;
    }

Perfect, you have completed your vending machine java program. You can test it by executing the Main class.

In case you would like to create an executable file so you can share your new program with your friend, check this article where I explain how to package a java program.

Source Code

All source code is available on Github

Conclusion

To summarize, this tutorial covers how to create a vending machine java program following an object-oriented programming approach. We went from defining requirements to create a skeleton implementation of our program and finally complete our vending machine java program.

I hope you enjoy the article and find it useful, and thank you so much for reading and supporting this blog!

Happy Coding!

More Interesting Articles

Project-Based Programming Introduction

Steady pace book with lots of worked examples. Starting with the basics, and moving to projects, data visualisation, and web applications

100% Recommended book for Java Beginners

Unique lay-out and teaching programming style helping new concepts stick in your memory

90 Specific Ways to Write Better Python

Great guide for those who want to improve their skills when writing python code. Easy to understand. Many practical examples

Grow Your Java skills as a developer

Perfect Boook for anyone who has an alright knowledge of Java and wants to take it to the next level.

Write Code as a Professional Developer

Excellent read for anyone who already know how to program and want to learn Best Practices

Every Developer should read this

Perfect book for anyone transitioning into the mid/mid-senior developer level

Great preparation for interviews

Great book and probably the best way to practice for interview. Some really good information on how to perform an interview. Code Example in Java