裝飾者模式:動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
設計原則:類應該對擴展開放,對修改關閉。
我們的目標是允許類容易擴展,在不修改現有代碼的情況下,就可搭配新的行爲。這樣的設計具有彈性可以應對改變,可以接受新的功能來應對改變的需求。
類圖
ConcreteComponent是我們要動態地加上新行爲的對象,它擴展自Component。
每個裝飾者都“有一個”(包裝一個)組件,也就是說,裝飾者有一個實例變量以保存某個Component的引用。
Beverage.java
/**
*Beverage(Component)是一個抽象類,有兩個方法:getDescription()及cost()
*/
package headfirst.decorator.starbuzz;
public abstract class Beverage {
String description = "Unknown Beverage";
//getDescription()已在此實現,而cost需在子類中實現
public String getDescription() {
return description;
}
public abstract double cost();
}
CondimentDecorator.java
/**
*必須讓Condiment Decorator能取代Beverage,所以CondimentDecorator擴展自Beverage類
*/
package headfirst.decorator.starbuzz;
public abstract class CondimentDecorator extends Beverage {
//所有調料裝飾者必須重新實現getDescription()
public abstract String getDescription();
}
Espresso.java
/**
*ConcreteComponent擴展自Beverage
*/
package headfirst.decorator.starbuzz;
public class Espresso extends Beverage {
public Espresso() {
//description繼承自Beverage
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
Mocha.java
/*
*ConcreteDecorator繼承自CondimentDecorator,而CondimentDecorator擴展自Beverage
*/
package headfirst.decorator.starbuzz;
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();
}
}