设计模式之 装饰器 Decorator
#Intent
Attach additional responsibilities to an object dynamically.Decorators provide a flexible alternative to subclassing for extending functionality.
为对象动态添加责任.装饰者提供了扩展功能的一种比继承更灵活的方法.
###认识装饰者模式
用继承无法解决的问题:类数量爆炸,设计死板,基类加入的新功能并不适用于所有的子类.
- 装饰者和被装饰者有相同的父类
- 你可以用一个或者多个装饰者包装一个对象
- 既然装饰者和被装饰者有相同的超类型,所以在任何需要原始对象(被包装)的场合,可以用装饰过的对象代替它.
- 装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的.
- 对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用你喜欢的装饰者来装饰对象.
#类图
- Decorator继承了Component,这么做的重点在于,装饰者和被装饰者必须是一样的类型,也就是有共同的超类,在这里,我们用继承达到类型匹配,而不是利用继承获得"行为"
- 装饰者需要和被装饰者有相同的“接口”,因为装饰者必须能取代被装饰者.新的行为是从哪里来的?我们将Decorator与component组合时,就是在加入行为.所得到的新行为,并不是继承自超类,而是由组合对象得来的.行为来自装饰者和component或者与其他装饰者之间的组合关系.
- 如果以来继承,那么类的行为智能在编译时动态决定.in other word,行为如果不是来自超类,就是子类overide后的版本.In the opposite,利用组合,可以把decorator混着用,而且是在运行时;
- 如果异类继承,每次需要新的行为时,还得修改现有代码;
###具体例子的类图
#代码
|
|
|
|
|
|
|
|
|
|
#讨论
####优点
- 比静态的继承更灵活:与对象的静态继承相比,Decorator提供了更加灵活的想对象添加responsbility 的方式,可以使用添加和分离的方法,在运行时增加和删除职责.使用继承机制增加responsbility需要创建新的子类,如果要为原来已有的所有子类增加新功能的话,每个子类都要重写,增加系统的复杂度,此外可以为一个特定的Component类提供多个Decorator,这种混合匹配是使用继承很难做到的.
- 打个比方:盖楼用建筑构件,写oo程序用类,制造构件(写类)是编译时(compile-time),而用构件盖楼(用类)是运行时(run-time);如果不用decorator,那么要使用新的形状的构件(新功能的类),那么必须重新烧新的构件(编写新的类),会造成生产过程不能标准化,生产效率太低了;如果使用了decorator,那么就可以在写类时只写基础的组件(制造标准的建筑组件(砖头,楼板等)),在使用的时候用装饰器把基础组件包装起来,产生新的功能满足不同的需求
- 避免在层次结构的高层类中提供太多特征,Decorator模式提供了一种”即用即付”的方法来添加职责,他并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反可以定义一个简单的类,并且用Decorator类给他逐渐的添加功能,可以从简单的部件组合出复杂的功能.
- 把添加职责的活动从编写类时推迟到使用类时,因为在编写类的时候,不可能知道所有新功能是什么,所以把类设计为可以定制新功能的结构,让类的用户自己添加要增加的新功能这就避免了在设计类的时候需要用子类来扩展功能的局限性(子类爆炸)
####缺点
- Decorator会在设计中加入大量的小类,这会偶尔导致别人不容易了解Decorator的设计方式
- 从对象的角度出发,被装饰的对象和它原来的对象不是一个对象,被装饰的对象只是调用了原来对象的方法,并且在原来对象的方法附近添加了新的操作.一旦使用装饰者模式,不止需要实例化组件,还要把此组件包装进装饰者中.(工厂和生成器模式对这个问题有帮助)
OO设计的一点总结
- 继承属于扩展的形式之一,但不见得是达到弹性设计的最佳方式;
- 在我们的设计中,应该允许行为可以被扩展,而无需修改现有的代码;
- 组合和委托可用于在运行时动态的加上新的行为;
- 除了继承,装饰者模式也可以让我们扩展行为;
- 装饰者模式意味着一群装饰者类,这些类用来包装具体组件;
- 装饰者类反映出被装饰的组件类型;
- 装饰者可以在被装饰者的行为附近加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的;
- 可以用无数个装饰者包装一个组件
- 装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型;
- 装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂;