參考書籍:
Head First Design Patterns (這是一本學Design Pattern 很好的書,漫畫形式,很易看易懂)
參考連結:
Wiki Decorator Pattern神人對Decorator Pattern 的文章 (這篇文章好清楚,如果沒有書看這個也很簡單易明。)
簡單來說,如果有一些物件是同時有[相同特性]和[相似特性]時,就很適合用Decorator Pattern。
就舉台式飲品為例,各式台式飲品都有相同的特性,例如產品名稱、基本價格、等等。
也可以相似的特性,例如加各式配料,加珍珠、加仙草、等等
在這個例子,相同的特性就放在Component 去實現,相似特性就放到Decorator 去實現。
Component 的抽象類別,將相同的特性如產品名稱、基本價格都放在這裡:
package decorator.beverage;
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
Component 的實作,假設我們的小店只有奶茶和奶綠兩種飲品:
package decorator.beverage;
public class MilkTea extends Beverage {
// override the abstract class description
public MilkTea(){
description = "Milk Tea";
}
// implement the abstract method
public double cost() {
return 1.99;
}
}
package decorator.beverage;
public class MilkGreenTea extends Beverage {
// override the abstract class description
public MilkGreenTea(){
description = "Milk GreenTea";
}
// implement the abstract method
public double cost() {
return 2.99;
}
}
然後就是Decroator 的抽象類別:
package decorator.beverage.flavouring;
import decorator.beverage.Beverage;
public abstract class FlavouringDecorator extends Beverage {
// Decorator should reimplement this to decorate the beverage
public abstract String getDescription();
}
然後是Decorator 的實作,假設我們有三種Decorator,冰的、加珍珠、加仙草:
package decorator.beverage.flavouring;
import decorator.beverage.Beverage;
public class Iced extends FlavouringDecorator {
Beverage drink;
//Decorator must have the base beverage
public Iced(Beverage drink){
this.drink = drink;
}
// Decorate the description of the beverage
public String getDescription() {
return "Iced " + drink.getDescription();
}
// Add the cost of Jelly to the beverage
public double cost() {
return drink.cost() + 0.20;
}
}
package decorator.beverage.flavouring;
import decorator.beverage.Beverage;
public class Pearl extends FlavouringDecorator {
Beverage drink;
//Decorator must have the base beverage
public Pearl(Beverage drink){
this.drink = drink;
}
// Decorate the description of the beverage
public String getDescription() {
return drink.getDescription() + ", with Pearl";
}
// Add the cost of pearl to the beverage
public double cost() {
return drink.cost() + 0.5;
}
}
package decorator.beverage.flavouring;
import decorator.beverage.Beverage;
public class Jelly extends FlavouringDecorator {
Beverage drink;
//Decorator must have the base beverage
public Jelly(Beverage drink){
this.drink = drink;
}
// Decorate the description of the beverage
public String getDescription() {
return drink.getDescription() + ", with Jelly";
}
// Add the cost of Jelly to the beverage
public double cost() {
return drink.cost() + 0.70;
}
}
最後就是我們的小店貢X開店了,我們點了三種飲品,分別是凍仙草奶茶、珍珠奶綠、凍珍珠奶茶......
package decorator;
import decorator.beverage.*;
public class GongTea {
public static void main(String[] args) {
//凍仙草奶茶
Beverage beverage1 = new MilkTea();
beverage1 = new Iced(beverage1);
beverage1 = new Jelly(beverage1);
System.out.println("Beverage1 is " + beverage1.getDescription() + ", price is $" + beverage1.cost());
//珍珠奶綠
Beverage beverage2 = new MilkGreenTea();
beverage2 = new Pearl(beverage2);
System.out.println("Beverage2 is " + beverage2.getDescription() + ", price is $" + beverage2.cost());
//凍珍珠奶茶
Beverage beverage3 = new MilkTea();
beverage3 = new Iced(beverage3);
beverage3 = new Pearl(beverage3);
System.out.println("Beverage3 is " + beverage3.getDescription() + ", price is $" + beverage3.cost());
}
}
運行的結果如下: