一、定义
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。装饰类通常会通过构造方法接受被装饰的对象。并基于被装饰对象的功能,提供更强的功能。
二、装饰者模式的优点
装饰模式比继承更灵活,避免了继承体系的臃肿;而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能。所以装饰类和被装饰类通常都属于一个体系。
利用组合和委托可以在运行时具有继承行为的效果。利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
通过动态地组合对象,可以写新的代码添加新功能,而无须修改现有代码。既然没有改变现有代码,那么引进bug或产生意外副作用的机会将大幅度减少。
开放-关闭原则
类应该对扩展开放,对修改关闭。也就是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。这样的设计具有弹性可以应对改变,可以接受新的功能来应对改变的需求。
三、装饰模式在Java中的应用:Java I/O
InputStream
|---FileInputStream
|---StringBufferInputStream
|---ByteArrayInputStream
|---FilterInputStream
|---PushbackInputStream
|---BufferedInputStream
|---DataInputStream
|---FilterInputStream
- InputStream是抽象组件。
- FileInputStream、StringBufferInputStream、ByteArrayInputStream是可以被装饰者包起来的具体组件。还有其他类,例如ObjectInputStream这里就没写了。
- FilterInputStream是一个抽象装饰者。
- PushbackInputStream、BufferedInputStream等是具体装饰者。
装饰者和被装饰者(组件)必须是一样的类型,也就是共同的超类。这里也用到了继承,例如FileInputStream和FilterInputStream都继承InputStream。不过这里是通过继承达到类型匹配,而不是用继承获得行为。从而装饰者能够取代被装饰者。而行为从哪里来?
当我们将装饰者与组件组合时,就是在加入新的行为。所得到的新行为,并不是继承自超类,而是由组合对象得来的。
四、装饰者设计模式的缺点
- 在设计中会加入大量的小类,导致使用者不容易了解它的设计方式
- 采用装饰者在实例化组件时,会增加代码的复杂度。一旦使用装饰者模式,不只需要实例化组件,还要把此组件包装进装饰者中,可能有很多层。