...a topping is not a pizza so why should it inherit the pizza class?
This comment was answered in the subsequent one: it's simply an issue of naming. Each topping should be named PizzaWithTopping.
...use an array to add or remove toppings from a pizza?
This solution makes a couple of assumptions.
- Do you own the
Pizza
class? You might be making pizzas for a specific store, where the Pizza
is determined by a franchise. One way the franchise controls quality is by not allowing individual stores to edit the base Pizza
code.
- Is a
Pizza
object mutable? Mutability leads to bugs that immutability can avoid. This is a bigger architectural decision than just editing an array.
Why should we consider using the decorator pattern in a situation like this?
The main advantage of the Decorator pattern over a "collection of enhancements" is that Decorator obeys the Open-Closed Principle. Decorator applies equally to any class, whether you own it or not, and whether the enhancements are foreseeable or not.
A collection requires that you either,
- See the future and plan ahead by adding a collection (of enhancements with the right interface) to every base class, or...
- Edit the existing base class in violation of the OCP.
In a well-known and relatively small domain like Pizza, this might not be a serious problem. Maybe the toppings never become more complex than adding one-at-a-time through a single API. But with the Decorator, you're covered either way.