原文:http://www.blogjava.net/sterning/archive/2008/01/21/176679.html
一、要完成的任務
星巴茲(Starbuzz)是以擴張速度最快而聞名的咖啡連鎖店。如果你在街角看到它的店,在對面街上肯定還會看到另一家。因爲擴張速度實在太快了,他們準備更新訂單系統,以合乎他們的飲料供應要求。他們原先的類設計是這樣的……
購買咖啡時,也可以要求在其中加入各種調料,例如:蒸奶(Steamed Milk)、豆漿(Soy)、摩卡(Mocha,也就是巧克力風味)或覆蓋奶泡。星巴茲會根據所加入的調料收取不同的費用。所以訂單系統必須考慮到這些調料部分。
二、Decorator模式
1、一個原則
類應該對擴展開放,對修改關閉
2、定義裝飾者模式
裝飾者模式動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
3.分析任務
4.設計任務
三、代碼實現
1.定義抽象類
(1)飲料抽象類Beverage
Beverage.java
/*
* Beverage是一個抽象類,有兩個方法
*/
public abstract class Beverage {
public String description="Unknown Beverage";
/*
* getDescription()已經在此實現了,但是cost()必須在子類中實現
*/
public String getDescription() {
return description;
}
public abstract double cost();
}
(2)調料抽象類CondimentDecorator
CondimentDecorator.java
/*
* 首先,必須讓CondimentDecorator能夠取代Beverage,所以將CondimentDecorator擴展自Beverage類
*/
public abstract class CondimentDecorator extends Beverage {
//所有的調料裝飾者都必須重新實現getDescription()方法.
public abstract String getDescription();
}
2.飲料實現
(1)Espresso
Espresso.java
/*
* 首先,必須讓CondimentDecorator能夠取代Beverage,所以將CondimentDecorator擴展自Beverage類
*/
public abstract class CondimentDecorator extends Beverage {
//所有的調料裝飾者都必須重新實現getDescription()方法.
public abstract String getDescription();
}
(2)HouseBlend
HouseBlend.java
import com.sterning.ch3_decorator.Beverage;
public class HouseBlend extends Beverage {
public HouseBlend() {
description="House Blend Coffee";
}
@Override
public double cost() {
return 0.89;
}
}
(3)DarkRoast
DarkRoast.java
import com.sterning.ch3_decorator.Beverage;
public class DarkRoast extends Beverage {
public DarkRoast() {
description="Dark Roast Coffee";
}
@Override
public double cost() {
return 0.99;
}
}
(4)Decaf
Decaf.java
import com.sterning.ch3_decorator.Beverage;
public class Decaf extends Beverage {
public Decaf() {
description="Decaf Coffee";
}
@Override
public double cost() {
return 1.05;
}
}
3.調料實現
(1)Mocha
Mocha.java
import com.sterning.ch3_decorator.Beverage;
import com.sterning.ch3_decorator.CondimentDecorator;
public class Mocha extends CondimentDecorator {
/*
* 要讓Mocha能夠引用一個Beverage,做法如下:一是用一個實例變量記錄飲料,也就是被裝飾者.
* 二是想辦法讓裝飾者(飲料)記錄到實例變量中,即把飲料當作構造器的參數,再由構造器將此飲料記錄在實例變量中
*/
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
/*
* 我們希望敘述不只是描述飲料,而是完整的連調料都描述出來
*/
return beverage.getDescription()+",Mocha";
}
@Override
public double cost() {
/*
* 要計算帶Mocha飲料的價錢,首先把調用委託給裝飾對象,以計算價錢,然後再加上Mocha的價錢,得到最後結果
*/
return 0.20+beverage.cost();
}
}
(2)Soy
Soy.java
import com.sterning.ch3_decorator.Beverage;
import com.sterning.ch3_decorator.CondimentDecorator;
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return .15 + beverage.cost();
}
}
(3)Whip
Whip.java
import com.sterning.ch3_decorator.Beverage;
import com.sterning.ch3_decorator.CondimentDecorator;
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double cost() {
return .10 + beverage.cost();
}
}
4.測試類StarbuzzCoffee
StarbuzzCoffee.java
import com.sterning.ch3_decorator.condiment.Mocha;
import com.sterning.ch3_decorator.condiment.Soy;
import com.sterning.ch3_decorator.condiment.Whip;
import com.sterning.ch3_decorator.drink.DarkRoast;
import com.sterning.ch3_decorator.drink.Espresso;
import com.sterning.ch3_decorator.drink.HouseBlend;
public class StarbuzzCoffee {
public static void main(String args[]){
/*
* 訂一杯Espresso,不需要調料,打印出它的描述和價錢.
*/
Beverage beverage=new Espresso();
System.out.println(beverage.getDescription()+" $"+beverage.cost());
/*
* 製造一個DarkRoast對象,用Mocha,Whip裝飾它
*/
Beverage beverage2=new DarkRoast();
beverage2=new Mocha(beverage2);
beverage2=new Mocha(beverage2);
beverage2=new Whip(beverage2);
System.out.println(beverage2.getDescription()+" $"+beverage2.cost());
/*
* 最後,再來一杯調料爲豆漿,摩卡\奶泡的HouseBlend咖啡
*/
Beverage beverage3=new HouseBlend();
beverage3=new Soy(beverage3);
beverage3=new Mocha(beverage3);
beverage3=new Whip(beverage3);
System.out.println(beverage3.getDescription()+" $"+beverage3.cost());
}
}
源代碼下載:ch3_decorator.rar