动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。
实例:创建自行车的装饰者
1、接口在装饰者模式中的角色:
装饰者模式颇多得益于接口的使用。装饰者最重要的特点之一
就是它可以用来替代其组件。
接口说明了装饰者必须实现哪些方法,有助于防止开发过程中的错误。
如果装饰者对象与其组件不能互换使用,它就丧失了其功用。这是装饰者模式的关键特点,要注意防止装饰者和组件出现的接口方法的差异。
这种模式的好处之一就是可以透明的用新对象装饰现有系统中的对象,
这并不会改变代码中的其他东西,只有装饰者和组件实现了同样的接口才能做到这一点。
2、装饰者模式与组合模式的比较:
相同点:
装饰者对象和组合对象都是用来包装别的对象(组合模式:子对象,装饰者模式:组件)
都与所包装的对象实现同样的接口并且会把任何方法调用传递给这些对象
不同点:
组合模式是一种结构型模式,用于把众多子对象组织为一个整体。通常并不需要修改方法调用,而只是将其沿组合对象与子对象的链向下传递,直到到达并落实在叶对象上。
装饰者模式也是一种结构型模式,但它并非用于组织对象,
而是用于在不修改现有对象或从派生子类的前提下为其增添职责。创建装饰者的目的就在于对方法进行修改,其做法是先传递方法调用,然后修改其返回结果。
组合对象不修改方法调用,着眼在于组织对象,而装饰者存在的唯一目的就是修改方法调用而不是组织子对象,因为子对象只有一个。
3、装饰者修改其组件的方式
在方法之后添加行为
在方法之前添加行为
替换方法
有时候为了实现新行为必须对方法进行整体替换。在此情况下,组件方法不会被调用(或虽然被调用但其返回值会被抛弃)。
添加新方法
与新方法装饰组件对象想必对现有方法进行修改更容易实施,而且更不容易出错,这是因为采用后一种做法时,被装饰的对象用起来与之前没什么不同,外围代码也就不需要修改了。
话虽如此,在装饰着中添加新方法又是也是为类增加功能的一种强有力的手段。我们可以用这种装饰者为自行车对象增添一个按铃方法。这是一个新功能,没有装饰者自行车就不可能执行这个任务。(见例子)
详细的例子:example
4、工厂的角色
如果必须确保按照某种特定顺序创建装饰者,那么可以为此使用工厂对象。实际上,不管顺序是否要紧,工厂都很适合于创建装饰对象。
用工厂实例化自行车对象有许多好处。首先,不必了解自行车和装饰者的各种类名,所有这些信息都封装在AcmeBicycleShop类中。因此添加自行车型号和选件非常容易,
只要把它们添加到AcmeBicycleShp.models或AcmeBicycleShop.options数组中即可。
例子:
AcmeBicycleShop类的createBicycle方法,以便用户可以指定自行车要配的选件。
通过上面例子最后创建带装饰的自行车对象的两种不同做法,可以发现,第一种方法与客户代码紧密耦合在一起的类不下5个,第二种方法使用了工厂,与客户代码耦合在一起的只有一个类,即那个工厂本身。
4、函数装饰者
装饰者并不局限于类,你也可以创建用来包装独立的函数和方法的装饰者。
example:
5、装饰者模式的适用场合
如果需要为类增添特性或职责,而从该类派生子类的解决办法并不实际的话,就应该适用装饰者模式。派生子类之所以会不实际,最常见的原因是需要增添的特性的数量和组合要求适用大量子类。
如果需要为对象添加特性而又不想改变使用该对象的代码的话,也可以采用装饰者模式。因为装饰者可以动态而又透明地修改对象,所以它们很适合于修改现有系统这一任务。
6、示例:方法性能分析器
本例要创建的装饰者可以用来包装任何对象以便为其提供方法性能分析功能。我们打算在每一个方法的前后添加一些代码,分别用于启动计时器和停止计时器并报告结果。
example
7、装饰者模式之利
装饰者是在运行期间为对象增添特性或职责的有工具。
装饰者的运行过程是透明的,这就是说你可以用它包装其他对象,然后继续按之前使用那些对象的方法来使用它。装饰者为程序员带来了极大的灵活性。
8、装饰者模式之弊
在遇到用装饰者包装起来的对象时,那些依赖于类型检查的代码会出问题。
使用装饰者模式往往会增加架构的复杂程度。此外,实现具有动态接口的装饰者(如MethodProfiler)涉及的语法细节有时也会令人生畏。在设计一个使用了装饰者模式的架构时,你需要多花点心思,确保自己的代码有良好的文档说明,并且容易理解。
The-Decorator-Pattern
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
parent directory.. | ||||