...
Code Block |
---|
|
package DecoratorPatternDemo;
public interface Beverage {
String getDescription();
double getCost();
}
|
Code Block |
---|
|
package DecoratorPatternDemo;
public interface CondimentDecorator extends Beverage {
}
|
Code Block |
---|
|
package DecoratorPatternDemo;
public class Coffee implements Beverage {
@Override
public String getDescription() {
return "Coffee";
}
@Override
public double getCost() {
return 1.99;
}
}
|
Code Block |
---|
|
package DecoratorPatternDemo;
public class Milk implements CondimentDecorator {
private Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
@Override
public double getCost() {
return beverage.getCost() + 0.30;
}
}
|
Code Block |
---|
|
package DecoratorPatternDemo;
public class CoffeeShopDriver {
public static void main(String[] args) {
// Order a coffee
Beverage beverage = new Coffee();
// Add milk to the coffee
beverage = new Milk(beverage);
// Print description and cost
System.out.println(beverage.getDescription() + " $" + String.format("%.2f", beverage.getCost()));
}
}
|
...
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.