Decorator模式
《设计模式》:动态地给一个对象增加一点额外的职责。就增加的功能来说,Decorator比子类更灵活
案例
需求:为打印销售票据增添表头、页脚信息。
SalesOrder使用SalesTicket,SalesTicket承担打印的职责。
初步设计如下:
但是这种设计存在问题:
如果必须处理很多不同类型的表头和页脚,每次只打印一种类型,那么可以考虑使用Strategy模式。
但是如果一次要打印一个以上的表头和页脚,会导致组合爆炸。
解决方案
设计方案的类图如下:
Decorator模式 | 关键特征 |
---|---|
意图 | 动态地给一个对象添加职责 |
问题 | 要使用的对象将执行所需的基本功能。但是,可能需要对这个对象将添加某些功能,这些附加功能可能发生在对象的基础功能之前或之后。请注意,Java基类在I/O处理中广泛的使用了Decorator模式 |
解决方案 | 可以无需创建子类,而扩展一个对象的功能 |
参与者与协作者 | ConcreteComponent让Decorator对象为自己添加功能。有时候用ConcreteComponent派生类提供核心功能,在这种情况下ConcreteComponent类就不再是具体的,而是抽象的。Component类定义了所有这些类所使用的接口 |
效果 | 所添加的功能放在小对象中。能够动态添加功能。注意:虽然装饰对象可以再被装饰对象之前之后增加功能,但是对象链最终是ConcreteComponent对象 |
实现 | 抽象类表示原类和要添加到这个类的新功能。 装饰类中将对新功能的调用放在紧随其后对象的调用的之前或之后。 |
模式弊端:
如果装饰对象由不同组开发,不能保证没有异常抛出。如果让Client捕获异常就失去了Decorator模式的价值(需要完成比之前更多的任务)。
修改方案:
实现一个和ConcreteComponent对象接口相同的对象集合。它调用装饰对象,捕获后者没有捕获的异常。附加好处:装饰对象不必要与ConcreteComponent接口相同。