Pizza builder

Here's an approach to making good uses of interfaces for the simple version of Pizza Parlor where we're just trying to model a pizza.

Our goal is to be able to create objects that represent a pizza which has a certain size (small, medium, large, extra large) and toppings.

A slightly silly way to implementing Topping

A simple but somewhat silly way is to make separate classes for each kind of topping, Pepperoni, ExtraCheese, etc. where each class will implement the interface methods to return a specific value appropriate for the type of the topping. E.g.

public class Pepperoni implements Topping {
  public String name() { return "pepperoni"; }
  public int cost() { return 50; }
  public int price() { return 175; }
}

public class ExtraCheese implements Topping {
  public String name() { return "extra cheese"; }
  public int cost() { return 25; }
  public int price() { return 150; }
}

// etc.

That's fine but its silly because the only differences between the different classes will be the specific values encoded in their methods.

A bit more sophisticated

While technically each such class does implement the methods in a different way (they return different values) it would be even easier to define a single class where instances of the class are constructed with the specific values. But if we only need one class to represent all toppings, why not just define Topping as a class and skip the interface altogether?

To really get the benefit of defining a separate interface we need at least one more class that implements at least some of the methods in a more substantially different way.

One common pattern is to define a class that implements an interface by composing other instances of that same interface. For example, we could could write a Combo class that implements the Topping interface by keeping a list of Topping objects that make up the combo and then computing the cost and price of the combo by summing its components.

With that class we could make a Topping that represents a meat-lovers combo like:

Topping meatLovers = new ComboTopping(
  new SingleTopping("pepperoni"),
  new SingleTopping("sausage"),
  new SingleTopping("bacon"));

From the point of view of a Pizza a ComboTopping is just another Topping that can be added with the addTopping method even though it's more complicated than a single topping.

When a Pizza needs to compute the cost of it's toppings it just needs to ask its toppings how much they eat cost. But when one of it's toppings is a ComboTopping that topping will under the covers add up the costs of its constituent toppings.

If you want to be fancy you could define ComboTopping to include a discount factor so the price() of the combo is somewhat less than the sum of the toppings it comprises.