您的位置:首页 > 其它

设计模式学习笔记--Decorator装饰模式

2009-10-05 07:29 405 查看
Decorator装饰模式:主要用于动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。

先进入我们的例子:

程序如下图

Code

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace DecoratorCar

{

class Program

{

static void Main(string[] args)

{

ToyotaCar tcar = new ToyotaCar();

DecoratorCruiseCtrl dr = new DecoratorCruiseCtrl(tcar);

DecoratorGPSCtrl dc = new DecoratorGPSCtrl(dr);

dc.AddAccessary();

Console.ReadLine();

}

}

}

示例说明:


由上面的程式可以了解,未來要添加一个新的功能,例如:想加一个天窗SunRoof,只要寫一個和DecoratorCruiseCtrl以及DecoratorGPSCtrl功能一樣的class繼承Decorator。这个個模式最有趣的是,Decorator既繼承了AbsCar,也合成AbsCar, 也就是说 Decorator 是装饰者模式里非常特殊的一个类,它既继承于 AbsCar【IS A关系】,又维护一个指向 AbsCar实例的引用【HAS A关系】,换个角度来说,Decorator 跟 AbsCar之间,既有动态组合关系,又有静态继承关系。

1、为什么要这样设计?我们知道,组合的好处是可以在运行时给对象增加职责,Decorator【HAS A】AbsCar的目的,是让 Decorator可以在运行时动态地给 AbsCar增加职责,这一点相对来说还比较好理解;

2、Decorator继承于 AbsCar的目的是什么?目的只有一个,那就是统一「装饰者」(DecoratorCruiseCtrl,DecoratorGPSCtrl或者其它任何想加的具体Decorator)和「被装饰者」(丰田车或者其它任何品牌的车)的接口。换个角度来说,不管是什么被装饰者(丰田车)还是「装饰者」(DecoratorCruiseCtrl,DecoratorGPSCtrl),它们都继承自最顶层的 AbsCar 基类,用户代码可以把它们统一看作 AbsCar来处理,这样带来的更深一层好处就是,「装饰者」对象(DecoratorCruiseCtrl,DecoratorGPSCtrl),对「被装饰者」对象(丰田车)的功能职责扩展,对用户代码来说是完全透明的,因为用户代码引用的都是 AbsCar,所以就不会因为「被装饰者」(丰田车)对象在被装饰后,引用它的用户代码发生错误,实际上不会有任何影响,因为装饰前后,用户代码引用的都是 AbsCar 类型的对象。

因此「装饰模式」通过继承,实现统一了「装饰者」和「被装饰者」的接口,通过组合获得了在运行时动态扩展「被装饰者」对象的能力。

程序运行效果:



总结:

Decorator Pattern 适用的情景:

你拥有一个已存在的组件类,却无法继承它 (subclassing)。

能够动态地为对象添加职责 (添加状态和行为)。

改变类中的成员和行为,但不影响其他对象。

希望能便于职责的撤消。

不想用「继承」来扩展行为。其中一种原因是避免当一些功能要交叉搭配引用时,单独用「继承」来设计会产生太多的子类、太复杂的类图结构,另一种考量可能是因为类的定义被隐藏,或类的定义不能用于生成子类。

Decorator Pattern 的优点:

可避免单独使用「继承」时,在扩展时不够弹性,且可能衍生过多的子类。

扩展时不需要修改既有的代码。

可在执行时期,动态地添加新行为 (职责)。

Decorator Pattern 的缺点:

可能会在程序中出现许多的小型类,亦即需要编写很多 ConcreteDecorator 类 (具体装饰者)。

若过度使用 Decorator 模式,会让程序逻辑变得很复杂。

别人较不易理解设计方式及代码,排查故障、追踪和调试也比较困难。

Decorator Pattern 的其他特性:

每个要装饰的功能,都放在单独的类中。

我们可以用无数个装饰者,去包装一个组件。

「装饰者」可以在「被装饰者」前面或后面,添加自己的行为,甚至将「被装饰者」的行为整个取代掉,以达到特定的目的。

「被装饰者」并不需要知道它已经被「装饰」过了,亦即 Component 类 (对象) 并不需要知道 Decorator 类 (对象) 的存在,且 Decorator 也仅仅认识 Component。

前往:设计模式学习笔记清单
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: