解決問題
動態(tài)地為對象添加功能,這是相對于繼承而言的,繼承是在定義類的時候擴展功能,而Decorator_pattern 可以在運行時,動態(tài)地為對象添加功能。
應(yīng)用場景
需要為對象添加一系列功能,但需要添加的功能只有在運行的過程才能知道。比如wikipedia 上舉的咖啡的例子,客人要的咖啡可能需要添加糖、milk等等,在客戶點餐之前,你無法確定需要加哪些東西;另一方面,也要求添加的功能之前應(yīng)該是相互獨立的,不應(yīng)該有先后順序關(guān)系,否則會出問題。
原理圖UML
image
Component 實體對象與修飾器的公共接口
Component1指的是實體對象,即要進(jìn)行修飾的對象
Decorator 用來增增被修飾對象的行為
示例
還是用wikipedia上的例子吧, 比較容易理解
Component
// The interface Coffee defines the functionality of Coffee implemented by decorator
public interface Coffee {
public double getCost(); // Returns the cost of the coffee
public String getIngredients(); // Returns the ingredients of the coffee
}
ConcreteComponent
// Extension of a simple coffee without any extra ingredients
public class SimpleCoffee implements Coffee {
@Override
public double getCost() {
return 1;
}
@Override
public String getIngredients() {
return "Coffee";
}
}
decorator
// Abstract decorator class - note that it implements Coffee interface
public abstract class CoffeeDecorator implements Coffee {
protected final Coffee decoratedCoffee;
public CoffeeDecorator(Coffee c) {
this.decoratedCoffee = c;
}
public double getCost() { // Implementing methods of the interface
return decoratedCoffee.getCost();
}
public String getIngredients() {
return decoratedCoffee.getIngredients();
}
}
// Decorator WithMilk mixes milk into coffee.
// Note it extends CoffeeDecorator.
class WithMilk extends CoffeeDecorator {
public WithMilk(Coffee c) {
super(c);
}
public double getCost() { // Overriding methods defined in the abstract superclass
return super.getCost() + 0.5;
}
public String getIngredients() {
return super.getIngredients() + ", Milk";
}
}
// Decorator WithSprinkles mixes sprinkles onto coffee.
// Note it extends CoffeeDecorator.
class WithSprinkles extends CoffeeDecorator {
public WithSprinkles(Coffee c) {
super(c);
}
public double getCost() {
return super.getCost() + 0.2;
}
public String getIngredients() {
return super.getIngredients() + ", Sprinkles";
}
}
public class Main {
public static void printInfo(Coffee c) {
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
}
public static void main(String[] args) {
Coffee c = new SimpleCoffee();
printInfo(c);
c = new WithMilk(c);
printInfo(c);
c = new WithSprinkles(c);
printInfo(c);
}
}