意图
不使用创建子类的方法动态的增加类的功能。
结构
模式的参与者如下:
Compeonent:定义一个对象接口,可以动态添加这些对象的功能。
ConcreteComponent:定义一个对象,可以动态的为其添加一些功能。
Decorator:维持一个对Component对象的引用,并定义与Component接口的一致接口。
ConcreteDecorator:为组件添加功能。
下面举的是一个为数据访问类添加日志功能的例子。
数据访问类包括支持SQLServer、Oracle和OLE三种类型的数据库访问的类。现在需要在数据库访问类的基础上增加记录数据库操作的日志功能。日志的记录方式可以是关系数据库或文件形式。
数据库访问类的抽象类:定义一个对象接口,可以动态添加这些对象的功能。
SQLServer的数据库访问类
Oracle的数据库访问类
OLE的数据库访问类
实现功能扩展的接口。
支持关系数据库的日志功能的类。
支持XML文件的日志功能的类。
获得具体类型的工厂
使用的代码
适用性
(1)在不影响其它对象的情况下,以动态且透明的方式添加单个对象的功能。
(2)处理那些可以撤销的功能。
(3)不能生成子类的方法扩充时。
效果
Decorator模式的优点是提供了比继承更加灵活的扩展,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。
BufferStream——.NET中的装饰模式
.NET中Decorator模式一个典型的运用就是关于Stream,它存在着如下的类结构:
可以看到, BufferedStream和CryptoStream其实就是两个包装类,这里的Decorator模式省略了抽象装饰角色(Decorator),示例代码如下:
改变外观还是改变内核
从适应对象变化的角度看,有两种方法可以达到目的,一种方法是制作一个小粒度的内核对象,然后进行包装,这是装饰模式实现的方法;另一种方法是制作一个大粒度的对象,其中包括不可变的部分和可变的部分,可变的部分可以采用策略模式实现。