装饰模式 -- Decorator

2017-03-30 19:44:08   最后更新: 2017-04-04 18:00:48   访问数量:313




有时,我们需要给某个对象动态添加一些功能,例如我们制作一个图形界面工具箱,允许为任意一个用户界面添加一些特性,例如添加边框、窗口滚动等

如果要通过继承的方式实现这样的需求,那么就必须为每一个用户界面组件类创建若干个子类,如拥有边框的 BroderTextView,支持滚动的 ScrollTextView,拥有边框并且支持滚动的 BroderScrollTextView,这样下去,如果有更多个被添加的特性,多个特性又有着若干种组合方式,那么我们的子类数目将会以几何级数向上增长

如果将组件嵌入到另一个对象中,由这个对象控制这些特性和行为的添加机制和时机,这将是一种非常灵活的方式,这就是装饰模式,他对使用该组件的客户是透明的,他只进行请求的转发,对于组件的请求,装饰对象将请求转发给被装饰的对象,但在转发前后可能会执行一些额外的动作,例如绘制边框或其他行为

 

 

 

如上图所示,装饰模式主要是由以下几个组件构成的:

  • Component -- 定义一个对象接口,定义供 client 使用的操作方法
  • ConcreteComponent -- 实际的被修饰对象,Component 的实现类
  • Decorator -- 抽象装饰类,维护一个指向 Component 对象的指针,并定义一个与 Component 接口一致的接口
  • ConcreteDecorator -- Decorator 的实现类,用来为 Component 添加属性或额外操作

 

client 通过多态机制实际操作的是 Decorator 对象,Decorator 对象负责转发给他的 Component 对象,并且有可能在转发的前后执行一些附加的操作

 

  1. Decorator 模式比静态继承更加灵活,可以动态添加和分离额外的操作,而如果使用继承机制继承机制则会很大程度上增加系统复杂度
  2. 用户实际看到的 Component 类是最为简洁的,避免了高层类拥有过多的特征

 

但是 Decorator 也同时拥有以下缺点:

  1. 从面向对象的角度出发,Decorator 是不应该继承自 Component 的,因为Decorator 作为一个透明的包装显然与实际的组件 Component 有着明显的区别,这在继承层次上无法体现出来,可能会让系统不便于被理解
  2. Decorator 模式会让系统产生许多小对象,对于系统的维护和异常的处理会变得很困难
  3. 对于非常复杂庞大的 Component 使用 Decorator 模式时,代价会非常高,此时使用 Strategy 模式将是一个更好的选择

 

有时我们会省略 Decorator 类,如果仅仅是为了添加一个额外操作,那么就无需定义抽象的 Decorator 类了,直接让 ConcreteDecorator 实现 Component,并接受请求

 

前面我们介绍了另一个结构型模式 -- Composite 模式:

组合模式 -- Composite

Decorator 与 Composite 两个模式有着相似的结构图,两者都基于递归组合来组织可变数目的若干对象,但两者有着本质的区别

Composite 的目的在于构造并组合所有的子类,使多个对象能够以一种统一的方式被处理,多个对象可以被当做一个对象来处理,从而减轻了系统复杂度,他的本质是对象的抽象表示

而 Decorator 模式的目的则是让你在不生成子类的情况下为对象添加新职责和属性,从而避免了子类的急剧增加,他的本质是对象的修饰

然而,这两个模式通常协同使用,此时,系统的抽象类将具有若干 Composite 子类和若干 Decorator 子类来处理更加复杂的情况

 






读书笔记      技术帖      龙潭书斋      设计模式      pattern      模式      design pattern      decorator      结构型模式      装饰模式      strategy     


京ICP备15018585号