【设计模式】之装饰模式(Decorator)
装饰模式的定义为 动态地为一个对象添加额外的功能,在扩展功能方面装饰模式比生成子类方式提供了一种更灵活的方法。
英文定义为:Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
装饰模式可以有效地避免太多继承而导致类爆炸的现象。
在open-close的原则下,装饰对于客户端因应该是透明的,只有这样才能保证可以动态地添加功能,否则每添加一次功能就需要修改一下客户端的调用方式。
decorator与component既是继承关系又是引用关系(has-a),decorator与Concrete Component都是继承自Component,这样的话只要客户端使用Component对象,即实现了多态的功能与隐藏装饰的功能。
在decotrator内部会有一个component的引用,decorator首先拦截送给component的消息,在真正调用component的消息处理之前and/or之后添加自己的功能,就像代码例子中的星巴克咖啡计算价格一样。
装饰模式的结构图如下:

因为具有动态添加功能的特性,所以与策略模式(Strategy)有相似之处,但是两者的delegation关系其实是正好相反的,decorator对于使用它的对象是透明,也就说被装饰的对象其实是不知道它被装饰了;而使用strategy的对象是明确地知道它使用的是什么strategy。decorator改变的是对象的"skin",而strategy改变的是对象的"gut"。
《Header First Design Patterns》中的给出的星巴克咖啡的例子如下,首先定义一个咖啡跟配料的基类Beverage,咖啡类的角色是concrete Component,配料就是Decorator,原因很明显,咖啡可以添加不同的配料,因此配料就可以装饰咖啡。
public class StarbuzzCoffee { public static void main(String[] args) { Beverage beverage = new Espresso(); System.out.println(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Whip(beverage2); System.out.println(beverage2.getDescription() + " $" + beverage2.cost()); Beverage beverage3 = new HouseBlend(); beverage3 = new Soy(beverage3); beverage3 = new Mocha(beverage3); beverage3 = new Whip(beverage3); System.out.println(beverage3.getDescription() + " $" + beverage3.cost()); }}结论:星巴克咖啡怎么那么便宜,唉,苦逼啊。。。