1、概念描述
该模式以对客户端透明的方式扩展对象的功能。
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者和被装饰者必须是一样的类型,这是相当关键的地方。我们利用继承达到"类型匹配",而不是利用继承获得"行为"。装饰者和被装饰者需具有相同的"接口",使得装饰者能够取代被装饰者;他们的行为,是通过组件之间的组合得到的。
涉及的角色:
(1)抽象构件角色:定义一个抽象接口,来规范准备附加功能的类。
(2)具体构件角色:将要被附加功能的类,实现抽象构件角色接口。
(3)抽象装饰者角色:持有对具体构件角色的引用并定义与抽象构件角色一致的接口。
(4)具体装饰角色:实现抽象装饰者角色,负责为具体构件添加额外功能。
注意点:
(1)装饰者和被装饰者必须具有相同的超类型。
(2)装饰者即可以包装被装饰者,也可以包装装饰者。往往利用多层包装来达到目的。
(3)装饰者中组合了被装饰者对象,这是装饰类的关键特征。正是由于这种组合,使得我们能够随心所欲的通过嵌套装饰来动态扩展行为。
2、实例
(1)、根据《Head First 设计模式》 装饰者模式应用到“星巴兹”咖啡店,类图如下
(2)、主体coffee
public abstract class Coffee { String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
(3)、被装饰者BrazilCoffee、JavaCoffee、Cappuccnio
public class BrazilCoffee extends Coffee { public BrazilCoffee(){ description ="BrazilCoffee"; } @Override public double cost() { return 1.99; } }
public class JavaCoffee extends Coffee { public JavaCoffee() { description = "JavaCoffee"; } @Override public double cost() { return 0.89; } }
public class Cappuccnio extends Coffee { public Cappuccnio(){ description = "Cappuccnio"; } @Override public double cost() { return 0.77; } }
(4)、装饰者类CoffeeDecorator
public abstract class CoffeeDecorator extends Coffee { public abstract String getDescription(); }
(5)、具体装饰者类Milk、Mocha
public class Milk extends CoffeeDecorator { Coffee cooffee; public Milk(Coffee cooffee) { this.cooffee = cooffee; } @Override public String getDescription() { return cooffee.getDescription() + ", Milk"; } @Override public double cost() { return 0.1 + cooffee.cost(); } }
public class Mocha extends CoffeeDecorator { Coffee cooffee; public Mocha(Coffee cooffee) { this.cooffee = cooffee; } @Override public String getDescription() { return cooffee.getDescription() + ", Mocha"; } @Override public double cost() { return 0.2 + cooffee.cost(); } }
......
(6)、测试类
public static void main(String[] args) { Coffee coffee = new JavaCoffee(); coffee = new Milk(coffee); coffee = new Mocha(coffee); System.out.println(coffee.getDescription() + "$" + coffee.cost()); }
(7)、结果
----------------------------------------
JavaCoffee, Milk, Mocha$1.19
----------------------------------------