设计原则:类应该对扩展开放,对修改关闭(开闭原则)。
装饰着模式:动态的将责任添加到对象上。若要扩展功能,装饰着将比继承更有弹性。
装饰着模式类图如下:
下面是关于装饰模式的一个典型示例:来自Head First的装饰者模式Demo(星巴兹咖啡):
package com.zjut.json.decoratorPattern; /** * 装饰模式抽象组件 * * @author json * * @date 2013-5-6 */ public abstract class Beverage { private String description = "Unknown Beverage"; public String getDescription(){ return description; } public void setDescription(final String description){ this.description = description; } public abstract double cost(); }
package com.zjut.json.decoratorPattern; /** * 浓缩咖啡-具体组件 * * @author json * * @date 2013-5-6 */ public class Espresson extends Beverage { /** * 增加具体咖啡描述 */ public Espresson(){ setDescription("Espresson"); } @Override public double cost() { return 1.99; } }
package com.zjut.json.decoratorPattern; /** * 具体组件 * * @author json * * @date 2013-5-6 */ public class HouseBlend extends Beverage { public HouseBlend(){ setDescription("House Blend Coffee"); } @Override public double cost() { return .98D; } }
package com.zjut.json.decoratorPattern; /** * 装饰者接口 * * @author json * * @date 2013-5-6 */ public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
package com.zjut.json.decoratorPattern; /** * @author json * * @date 2013-5-6 */ public class Mocha extends CondimentDecorator { /**被装饰着*/ private Beverage beverage; @Override public String getDescription() { return beverage.getDescription() + ", Mocha"; } @Override public double cost() { return beverage.cost() + .20D; } public Beverage getBeverage() { return beverage; } public void setBeverage(Beverage beverage) { this.beverage = beverage; } }
package com.zjut.json.decoratorPattern; /** * @author json * * @date 2013-5-6 */ public class StarbuzzCoffee { public static void main(String[] args){ Beverage decorated = new Espresson(); Mocha decorator = new Mocha(); decorator.setBeverage(decorated); System.out.println(decorator.cost()); //双份摩卡 Mocha doubleDecorator = new Mocha(); doubleDecorator.setBeverage(decorator); System.out.println(doubleDecorator.getDescription() + ": " + doubleDecorator.cost()); } }
在这个例子中,装饰者和被装饰着共同继承与抽象组件Beverage,但不同之处在于,装饰者继承抽象组件的是类型,而不是行为,而行为的继承是利用组合,即在具体装饰者对象中存在了一个被装饰者的引用,将被装饰者的行为委托给这个引用。