裝飾者模式說明:動態地將責任加於物件上,若要擴充功能,裝飾者提供了比繼承更有彈性的選擇。
- 裝飾者和被裝飾者有相同的超型態
- 你可以利用一個或多個裝飾者包裝一個物件
- 所以我們可以在任何需要傳遞原始的(被包裝的)物件場合,改以傳遞裝飾後的(包裝的)物件。
- 裝飾者可以在所委派被裝飾者的行為,之前或(與)之後加上自己的行為,達到目的。
- 物件可在任何時候被裝飾,所以可以在執行期動態地用任何適合的裝飾者,來裝飾物件。
結構介紹
Component 主要物件 (擁有主要的功能及行為)
ComponentIABC 主要物件實作
DecorateComponent 裝飾者物件 ( 幫助補充或增加主體的功能及行為。)
DecorateComponentABC 裝飾者物件實作

讓星巴茲咖啡也符合這框架吧
主類別
public abstract class Beverage { //飲料
String description = "是什麼飲料呢";
public String getDescrption(){
return description;
}
}
public abstract class CondimentDecorator extends Beverage{ //實踐一個裝飾者類別
protected abstract String getDescription();
}
實踐飲料吧(次類別)
public class Espresso extends Beverage{ //濃咖啡
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage{ //綜合咖啡(?)
public HouseBlend() {
description = "House Blend Coffee";
}
public double cost() {
return .89;
}
}
public class DarkRoast extends Beverage{ ... //黑咖啡
public class Decaf extends Beverage{ ... //低咖啡因
寫個各種配料 (裝飾者)
public class Mocha extends CondimentDecorator{ //摩卡
Beverage beverage; //用一個實體變數紀錄Beverage物件,也就是被裝飾者
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() { //讓被裝飾者(飲料)被記錄到實體變數中
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return .20 + beverage.cost();
}
}
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 .10 + beverage.cost();
}
}
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 .20 + beverage.cost();
}
}
...想喝什麼配料自己加囉
實作囉
public class Starbox{
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()+"$"+beverage.cost()); //輸出
//輸出: Espresso $1.99
Beverage beverage2 = new DarkRoast(); //黑咖啡物件
beverage2 = new Mocha(beverage2);//用摩卡裝飾
beverage2 = new Mocha(beverage2);//雙重摩卡
beverage2 = new Whip(beverage2);//用奶泡裝飾
System.out.println(beverage2.getDescription()+"$"+beverage2.cost());
//輸出: Dark Roast Coffe, Mocha, Mocha, Whip $1.49
Beverage beverage3 = new HouseBlend(); //混和咖啡物件
beverage2 = new Soy(beverage3);//用豆漿裝飾
beverage2 = new Mocha(beverage3);//用摩卡裝飾
beverage2 = new Whip(beverage3);//用奶泡裝飾
System.out.println(beverage2.beverage3()+"$"+beverage3.cost());
//輸出: House Blend Coffe, Soy, Mocha, Whip $1.34
}
}
如果可以點中杯、大杯、特大杯,且分別為不同價錢?
public class Soy extends CondimentDecorator{ //豆漿
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public int getSize() {
return beverage.getSize();
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
double cost = beverage.cost();
if(getSize()==Beverage.TALL){
cost +=.10;
}else if(getSize()==Beverage.GRANDE){
cost +=.15;
}else if(getSize()==Beverage.VENTI){
cost +=.15;
}
return cost;
}
}