********************************
The Decorator Pattern defined
**********************************
Decorating our Beverages
The four concrete components, one per coffee type.
只列出了 DarkRoast。
Let’s start with the Beverage class, which doesn’t need to change from Starbuzz’s original design. Let’s take a look:
public abstract class Beverage {
String description = “Unknown Beverage”;
public String getDescription() {
return description;
}
public abstract double cost();
}
Beverage is an abstract class with the two methods getDescription() and cost().
getDescription is already implemented for us, but we need to implement cost() in the subclasses.
Now that we’ve got our base classes out of the way, let’s implement some beverages. We’ll start with Espresso.
Remember, we need to set a description for the specific beverage and also implement the cost() method.
public class Espresso extends Beverage {
public Espresso() {
description = “Espresso”;
}
public double cost() {
return 1.99;
}
}
First we extend the Beverage class, since this is a beverage
To take care of the description, we set this in the constructor for the class.
Remember the description instance variable is inherited from Beverage.
Finally, we need to compute the cost of an Espresso.
We don’t need to worry about adding in condiments in this class, we just need to return the price of an Espresso: $1.99.
**********************************************
Beverage is simple enough. Let’s implement the abstract class for the Condiments (Decorator) as well:
First, we need to be interchangeable with a Beverage, so we extend the Beverage class
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
We’re also going to require that the condiment decorators all reimplement the getDescription() method.
Now it’s time to implement the concrete decorators. Here’s Mocha:
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + “, Mocha”;
}
public double cost() {
return .20 + beverage.cost();
}
}
Mocha is a decorator, so we extend CondimentDecorator. Remember, CondimentDecorator extends Beverage.
We’re going to instantiate Mocha with a reference to a Beverage using:
(1) An instance variable to hold the beverage we are wrapping.
(2) A way to set this instance variable to the object we are wrapping. Here, we’re going to to pass he beverage we’re wrapping to the decorator’s constructor.
We want our description to not only include the beverage - say “Dark Roast” - but also to include each item decorating the beverage, for instance, “Dark Roast, Mocha”. So we first delegate to the object we are decorating to get its description, then append “, Mocha” to that description.
Now we need to compute the cost of our beverage with Mocha. First, we delegate the call to the object we’re decorating, so that it can compute the cost; then, we add the cost of Mocha to the result.
****************************************
测试一下,
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()
+ “ $” + beverage.cost());
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()
+ “ $” + beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription()
+ “ $” + beverage3.cost());
}
}