装饰模式(Decorator)又名包装模式(Wrapper)。
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
装饰模式以对客户端透明的方式动态的给一个对象附加上更多的责任。
装饰模式的结构
模式的类图
角色如下:
- 抽象构件角色(Component): 给出一个抽象接口,以规范准备接受附加责任的对象。
- 具体构件角色(Concrete Component): 定义一个将要接收附加责任的类
- 装饰角色(Decorator): 持有一个构建(Component)对象的实例,并定义一个与抽象角色接口一致的接口。
- 具体装饰角色(Concrete Decorator): 负责给构建对象贴上附加的责任。
代码清单
构建类 Component
/** * 构建类 * @author Administrator * */ public interface Component { /** * 商业方法 */ void sampleOperation(); }
装饰类 Decorator
public class Decorator implements Component { private Component component; public Decorator(Component component){ this.component = component; } public Decorator(){ //write your code } /** * 商业方法,委派给构件 */ @Override public void sampleOperation() { // TODO Auto-generated method stub component.sampleOperation(); } }
具体构件类 ConcreteComponent
public class ConcreteComponent implements Component { public ConcreteComponent(){ } /** * 商业方法 */ @Override public void sampleOperation() { } }
具体装饰类
public class ConcreteDecorator extends Decorator { /** * 商业方法 */ public void sampleOperation() { super.sampleOperation(); } }
装饰模式应当在什么情况下使用
1. 需要扩展一个类的功能,或给一个类增加附加责任。
2. 需要动态的给一个对象增加功能,这些功能可以再动态的撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
装饰模式的优点和缺点
优点:
1 . 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
3. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错。
缺点:
使用装饰模式,可以比使用继承关系需要较少数目的类。
使用较少数目的类,当然使设计比较易于进行。
使用装饰模式会产生比使用继承关系更多的对象。
更多的对象会使的查错变的困难,特别是这些对象看上去都很相像。
模式的简化
大多数情况下,装饰模式的实现都比本节定义中给出的示意性实现要简单。
对模式进行简化时,要注意以下情况:
1. 一个装饰类的接口必须与被装饰类的接口相容。
2. 尽量保持 Component 作为一个轻类。
这个类的责任是为各个 ConcreteDecorator 类提供共同的接口,因此它应当着重在提供接口而不是存储数据。
3. 如果只有一个ConcreteComponent 类而没有抽象的 Component 类(接口),那么Decorator类经常可以是ConcreteCompoent的一个子类。
4. 如果只有一个ConcreteDecorator类,那么就没必要建立一个单独的 Decorator 类,可以把Decorator 和 ConcreteDecorator 的责任合并成一个类。
一个例子:发票系统
假设只有一个头部装饰类和一个尾部装饰类,设计图如下: