4
\$\begingroup\$

I was inspired by a previous post here that also wrote a pizza ordering application. This is the attempt I have made using OOP in mind as I thought that would be just the way to go.

Here is Pizza.java

import java.util.ArrayList;

public class Pizza {

    private String size;
    private ArrayList<String> toppings;

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public ArrayList<String> getToppings() {
        return toppings;
    }

    public void setToppings(ArrayList<String> toppings) {
        this.toppings = toppings;
    }

    public String toString() {
        return this.size + " pizza with " + this.getToppings();
    }
}

Here is PizzaOrder.java

import java.util.ArrayList;

public class PizzaOrder {
    private double totalOrderCost;

    private final ArrayList<Pizza> pizzas;

    public PizzaOrder(ArrayList<Pizza> pizzas) {
        this.pizzas = pizzas;
    }

    public void calculateTotalOrderCost() {
        final double LARGE_COST = 9.99;
        final double MEDIUM_COST = 7.99;
        final double SMALL_COST = 5.99;
        final double COST_PER_TOPPING = 0.5;

        for (Pizza pizza : pizzas) {
            switch (pizza.getSize()) {
                case "Large":
                    totalOrderCost += LARGE_COST;
                    break;
                case "Medium":
                    totalOrderCost += MEDIUM_COST;
                    break;
                case "Small":
                    totalOrderCost += SMALL_COST;
                    break;
                default:
                    totalOrderCost += 0.0;
                    break;
            }

            int totalToppings = pizza.getToppings().size();
            totalOrderCost += totalToppings * COST_PER_TOPPING;
        }
    }

    public double getTotalOrderCost() {
        return totalOrderCost;
    }

    public void printOrderSummary() {
        for (Pizza pizza : pizzas) {
            System.out.println("Ordered a " + pizza.getSize() + " pizza with " +    pizza.getToppings());
        }
        System.out.println("TOTAL ORDER AMOUNT: " + getTotalOrderCost());
    }
}

Here is the driver of the application

import java.util.Scanner;
import java.util.ArrayList;

public class PizzaOrderDriver {

    public static void printWelcomeMessage() {
        System.out.println("------------------------------------");
        System.out.println("Welcome to the Pizza Order Program!");
        System.out.println("------------------------------------");
    }

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

        printWelcomeMessage();

        ArrayList<Pizza> pizzas = new ArrayList<>();

        System.out.println("Enter the total pizzas you would like to order: ");
        int totalPizzas = scanner.nextInt();

        // Reading input regarding pizza size and pizza toppings
        for (int i = 0; i < totalPizzas; ++i) {
            Pizza pizza = new Pizza();

            ArrayList<String> toppings = new ArrayList<>();

            String pizzaSize;
            System.out.println("Enter the size of the pizza Large, Medium, Small: ");
            pizzaSize = scanner.next();
            pizza.setSize(pizzaSize);

            int totalToppings;
            System.out.println("Enter the total amount of toppings on the pizza: ");
            totalToppings = scanner.nextInt();

            for (int j = 0; j < totalToppings; ++j) {
                System.out.println("Enter the topping: ");
                String topping = scanner.next();
                toppings.add(topping);
            }

            pizza.setToppings(toppings);
            pizzas.add(pizza);
        }


        // Creating PizzaOrder object and relevant information with regards to order
        PizzaOrder order = new PizzaOrder(pizzas);
        order.calculateTotalOrderCost();
        order.printOrderSummary();


        // Cleanup
        scanner.close();
    }
}

Along with a general review, I would like some ideas on how to extend this even further. I know what I have right now is rather very simple.

Thank you for reviewing my code.

\$\endgroup\$
4
\$\begingroup\$
private String size;

Could be an Enum instead, or a class. Both could also hold their costs.


private ArrayList<String> toppings;

You should use the most generic interface of your types when declaring them as possible, as this allows to swap out the implementations without having to change everything. In this case it would be List.


public class Pizza {
    // ...
}

You're duplicating data, you don't need to keep track of the number of toppings, the list is already doing that for you. They can easily get out of sync and therefor cause trouble.

You have a problematic API here, by allowing to set a List directly:

  1. It will be null if not set. 2.null can be set.
  2. The List can be changed outside of the control of the class.

What would be a more clean solution would be to keep the List of toppings internal, and only expose a method to add (and if needed to remove) toppings. That would greatly simplify your class.

public class Pizza {
    private List<String> toppings = new ArrayList<>();

    public String getCount() {
        return toppings.size();
    }
    
    public Pizza addTopping(String topping) {
        toppings.add(topping);
        
        return this;
    }
    
    public String toString() {
        return toppings.length() + " pizza with " + toppings;
    }
}

Note that toppings.toString(), as it will be called for String concatenation, will not output the toppings at all.


totalOrderCost += totalToppings * COST_PER_TOPPING

Always remember that += is not shorthand for a = a + b but for a = (TYPE_A)(a + b). So it might silently truncate data.


You could rewrite the PizzaOrder according to the same changes as for Pizza to add Pizzas to the order, like this:

PizzaOrder pizzaOrder = new PizzaOrder();
pizzaOrder.add(createPizzaWithToppings());
pizzaOrder.add(createPizzaWithToppings());
pizzaOrder.add(createPizzaWithToppings());

Systemm.out.println(pizza.getTotalOrderCost());

            String pizzaSize;
            System.out.println("Enter the size of the pizza Large, Medium, Small: ");
            pizzaSize = scanner.next();

Just declare the variable on the same line as assigning it.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the advice in this review! I will be sure to implement these changes. Do you have any suggestions on how to extend this further? \$\endgroup\$
    – King Cold
    Sep 21 '20 at 18:58
  • \$\begingroup\$ Well, user input should be put into its own class. There should be an interface for that, so that the order can come from anywhere, as long as the interface is implemented. None of these classes should be concerned with their representation, that should be its own class, too. Then stop using doubles. And finally, all the prices and sizes should come from a configuration source, instead of being hardcoded. You can blow this up to a whole framework about ordering pizzas. \$\endgroup\$
    – Bobby
    Sep 21 '20 at 19:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.