Decorator Pattern Demo

package DecoratorPatternDemo; public interface Beverage { String getDescription(); double getCost(); }
package DecoratorPatternDemo; public interface CondimentDecorator extends Beverage { }
package DecoratorPatternDemo; public class Coffee implements Beverage { @Override public String getDescription() { return "Coffee"; } @Override public double getCost() { return 1.99; } }

 

Of course, let's break it down.

The Decorator pattern allows us to add new functionality to an existing object without altering its structure. This is done by wrapping the original object and providing additional functionality through the wrapper.

Our example models a coffee shop where you can order a basic coffee and then add different condiments to it. Each condiment added increases the price of the coffee.

Interfaces: We start with two interfaces:

  • Beverage: This is the basic interface that defines the required methods that all beverages must have, i.e., getDescription and getCost.

  • CondimentDecorator: This extends the Beverage interface. Any class that implements CondimentDecorator is also a Beverage, but with added functionality (in this case, the added functionality is an additional ingredient and cost).

Classes:

  • Coffee: This is a basic type of Beverage. It has a description and cost.

  • Milk: This class represents a condiment and it is a CondimentDecorator. It's constructed with a Beverage (which can be a basic coffee or a coffee with other condiments). When you call its getDescription method, it appends ", Milk" to the description of the beverage it was constructed with. When you call its getCost method, it adds $0.30 to the cost of the beverage it was constructed with.

The main method in the CoffeeShop class demonstrates how to use these classes and interfaces together. We create a Coffee object and then decorate it with a Milk object, and then print the description and cost.