设计模式-装饰

  1. 意图
  2. 例子
  3. 适用性
  4. 结构
  5. 协作
  6. 效果

意图

动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

例子

最好的例子就是ui图,在针对富文本进行编辑的时候,工具栏、文本栏、保存/取消栏等,都是是在其基础上进行装饰的效果。

首先是基础绘图组件

public interface VisualComponent {
public void draw();
}

以及具备该功能抽象类

pubic class abstract Decorator implements VisualComponet {

VisualComponent component;
void draw() {
component.draw();
}
}

接下来就可以使用抽象类的子类完成工作

public class BorderDecorator extends Decorator {
public BorderDecorator(VIsualComponent component) {
this.component = component;
}

void drawBorder() {
// TODO...
}

void draw() {
super.draw();
drawBorder();
}
}

这样在原有的基础draw上,增加了其他的操作。一层嵌套一层形成新的子类,并在原有基础上更具有针对性增加功能。

适用性

  1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  2. 处理那些可能撤销的职责
  3. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

结构

github

协作

Decorator 将请求转发给它的 Component 对象,并有可能在转发请求前后执行一些附加的动作。

效果

Decorator 模式至少有两个主要优点和两个缺点:

  1. 比静态继承更灵活
    与对象的静态继承(多重继承)相比,Decorator模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。相比之下,继承机制要求为每个添加的职责创建一个新的子类(例如,BorderScrollableTextView, BorderedTextView)。这会产生许多新的类,并且会增加系统的复杂度。此外,为一 个特定的Component类提供多个不同的Decorator类,这就使得你可以对一些职责进行混合和匹配。
    使用 Decorator 模式可以很容易地重复添加一个特性,例如在 TextView 上添加双边框时, 仅需将添加两个 BorderDecorator 即可。而两次继承 Border 类则极容易出错的。
  2. 避免在层次结构高层的类有太多的特征
    Decorator模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用Decorator类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能。这样,应用程序不必为不需要的特征付出代价。同时也更易于不依赖于 Decorator 所扩展(甚至是不可预知的扩展)的类而独立地定义新类型的Decorator。扩展一个复杂类的时候,很可能会暴露与添加的职责无关的细节。
  3. Decorator 与它的 Component 不一样
    Decorator是一个透明的包装。如果我们从对象标识的观点出发,一个被装饰了的组件与这个组件是有差别的,因此,使用装饰时不应该依赖对象标识。
  4. 有许多小对象
    采用Decorator模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在他们相互连接的方式上有所不同,而不是它们的类或是它们的属性值有所不同。尽管对于那些了解这些系统的人来说,很容易对它们进行定制,但是很难学习这些系统,排错也很困难。