装饰器模式

定义与特点

装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

装饰(Decorator)模式的主要优点有:

  • 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
  • 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

其主要缺点是:装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。

模式的结构

装饰模式主要包含以下角色。

  1. 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  3. 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  4. 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

装饰器模式与桥接模式

有意思的是与桥接模式类似都是有四个角色,,而且只单单从代码的角度来讲,他们的实现结构还有些相似:

不同的是Decorator与Component是继承、聚合关系,而Abstraction与Implementor只有聚合关系,相比之下装饰器模式是耦合更深的模式。下面是我分析出来的两点区别:

  1. 我上篇写桥接模式的文章中,写明了Abstraction角色定义了比Implementor高一层次的操作(具有一定业务含义的操作),这样来说Implementor本身的操作可以是没有独立的业务含义(单独存在的意义)的操作。而相较来说,装饰器的Component角色本身是有独立的使用使用场景(独立的业务含义)的,由于Decorator继承自Component,所以总归来说Decorator和Component是同一层次的操作,从继承来说只不过Decorator是Component的一种增强。
  2. Concrete Component可以是多层级(指的是类的层级)的装饰,可以叠加;而Concrete Implementor是同一层级的实现,彼此没有关联。

下面是我找到的其他解释,可以相互印证理解:

  1. 桥接模式中所说的分离,其实是指将结构与实现分离(当结构和实现有可能发生变化时)或属性与基于属性的行为进行分离;而装饰者只是对基于属性的行为进行封闭成独立的类。
  2. 桥接中的行为是横向的行为,行为彼此之间无关联;而装饰者模式中的行为具有可叠加性,其表现出来的结果是一个整体,一个各个行为组合后的一个结果。

装饰器模式与适配器模式

网上找到的解释如下:

  • 适配器模式的意义是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的。
  • 装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能。

个人理解下,适配器转换为另一个接口就不再适应原来的接口;而装饰器是在原来的接口之上增强,原来的接口还是适用的。

进阶

分析了这么多,但遇到真实场景的时候,还是可能分不清楚这个场景更适合哪种模式。如何来界定此场景是一个功能的增强而不是一个单独的扩展呢?还拿制作咖啡来说:原来只有加糖的咖啡,现在有了加奶的咖啡。我们需要思考此场景,分析业务操作,认识业务本质(又到了DDD范围 ≥Ö‿Ö≤ )。

如果感到快乐,你就拍拍手。