# 设计模式之装饰器模式
5 min read
Table of Contents
Decorator 装饰器模式。
装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。这也是判断是否该用装饰器模式的一个重要的依据。除此之外,装饰器模式还有一个特点,那就是可以对原始类嵌套使用多个装饰器。
为了满足这个应用场景,在设计的时候,装饰器类需要跟原始类继承相同的抽象类或者接口。
定义
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator 模式比生成子类(继承)更为灵活(消除重复代码和减少子类个数)== 《设计模式》GoF
UML
几条原则
来自《Head First 设计模式》的几条原则。
- 装饰者和被装饰者对象有相同的超类型。
- 你可以用一个或多个装饰者包装一个对象。
- 既然装饰者和被装饰者对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
- 装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的。
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
示例
interface Coffee { public double getCost();
public String getIngredients();}
class SimpleCoffee implements Coffee { @Override public double getCost() { return 1; }
public String getIngredients() { return "Coffee"; }}abstract class CoffeeDecorator implements Coffee { private final Coffee decoratedCoffee;
public CoffeeDecorator(Coffee c) { this.decoratedCoffee = c; }
@Override public double getCost() { return decoratedCoffee.getCost(); }
@Override public String getIngredients() { return decoratedCoffee.getIngredients(); }}
class WithMilk extends CoffeeDecorator { public WithMilk(Coffee c) { super(c); }
@Override public double getCost() { return super.getCost() + 0.5; }
@Override public String getIngredients() { return super.getIngredients() + ", Milk"; }}
class WithSprinkles extends CoffeeDecorator { public WithSprinkles(Coffee c) { super(c); }
@Override public double getCost() { return super.getCost() + 0.2; }
@Override 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); }}
// Cost: 1.0; Ingredients: Coffee// Cost: 1.5; Ingredients: Coffee, Milk// Cost: 1.7; Ingredients: Coffee, Milk, Sprinkles要点总结
通过采用组合而非继承的手法,Decorator 模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
Decorator 类在接口上表现为 is-a Component 的继承关系,即 Decorator 类继承了 Component 类所具有的接口。但在实现上又表现为 has-a Component 的组合关系,即 Decorator 类又使用了另一个 Component 类。
Decorator 模式的目的并非解决“多子类衍生的多继承”问题,Decorator 模式应用的要点在于解决“主体类在多个方向上的扩展功能”—是为“装饰”的含义。
个人观点
装饰器模式是最能体现开放封闭原则的一种模式。
装饰器模式是组合优先于继承最直观的一种模式。
参考链接
- Wiki: Decorator pattern
- 《李建忠:C++设计模式》- 装饰模式