索引

别名

  • 包装器(Wrapper)

意图

动态地给一个对象添加一些额外的职责。

就增加功能来说,Decorator 模式相比生成子类更为灵活。

Attach additional responsibilities to an object dynamically.

Decorators provide a flexible alternative to subclassing for extending functionality.

结构

参与者

Component

  • 定义一个对象接口,可以给这些对象动态地添加职责。

ConcreteComponent

  • 定义一个对象,可以给这个对象添加一些职责。

Decorator

  • 维持一个指向 Component 对象的指针,并定义一个与 Component 接口一致的接口。

ConcreteDecorator

  • 向组件添加职责。

适用性

在以下情况下可以使用 Decorator 模式:

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 处理那些可以撤销的职责。
  • 当不能采用生成子类的方法进行扩充时。

缺点

  • Decorator 是一个透明的包装,其与 Component 还是有些差别的。
  • 采用 Decorator 模式进行系统设计往往会产生许多看上去类似的小对象。导致很难学习系统,排错也很困难。

效果

  • 比静态继承更灵活。
  • 避免在层次结构高层的类有太多的特征。

相关模式

  • Decorator 模式不同于 Adapter 模式,因为 Decorator 仅改变对象的职责而不改变它的接口,而 Adapter 将给对象一个全新的接口。
  • 可以将 Decorator 视为一个退化的、仅有一个组件的 Composite。然而,Decorator 仅给对象添加额外的职责,它的目的不在于对象聚集。
  • 用一个 Decorator 可以改变对象的外表,而 Strategy 模式使得你可以改变对象的内核。这是改变对象的两种途径。
  • 当 Component 类原本就很庞大时,使用 Decorator 模式的代价太高,Strategy 模式相对更好一些。

实现

实现方式(一):Decorator 对象的接口必须与它所装饰的 Component 的接口保持一致。

所有的 ConcreteDecorator 类必须有一个公共的父类。

使用 Decorator 模式仅从外部改变组件,因此组件无需对它的装饰有任何了解,也就是说,这些装饰对该组件是透明的。

 namespace DecoratorPattern.Implementation1
{
public abstract class Component
{
public abstract void Operation();
} public class ConcreteComponent : Component
{
public override void Operation()
{
// do something
}
} public abstract class Decorator : Component
{
private Component _component; public Decorator(Component component)
{
_component = component;
} public override void Operation()
{
_component.Operation();
}
} public class ConcreteDecorator : Decorator
{
public ConcreteDecorator(Component component)
: base(component)
{
} public override void Operation()
{
base.Operation();
AddedBehavior();
} private void AddedBehavior()
{
// do some other things
}
} public class Client
{
public void TestCase1()
{
Component component1 = new ConcreteComponent();
Component component2 = new ConcreteDecorator(component1); component2.Operation();
}
}
}

实现方式(二):省略抽象的 Decorator 类。

当仅需要添加一个职责是,没有必要定义抽象的 Decorator 类。

这时可以把 Decorator 向 Component 转发请求的职责合并到 ConcreteDecorator 中。

 namespace DecoratorPattern.Implementation2
{
public abstract class Component
{
public abstract void Operation();
} public class ConcreteComponent : Component
{
public override void Operation()
{
// do something
}
} public class ConcreteDecorator : Component
{
private Component _component; public ConcreteDecorator(Component component)
{
_component = component;
} public override void Operation()
{
_component.Operation();
AddedBehavior();
} private void AddedBehavior()
{
// do some other things
}
} public class Client
{
public void TestCase1()
{
Component component1 = new ConcreteComponent();
Component component2 = new ConcreteDecorator(component1); component2.Operation();
}
}
}

设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。

设计模式之美:Decorator(装饰)的更多相关文章

  1. 设计模式(八)装饰器模式Decorator(结构型)

    设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...

  2. ④ 设计模式的艺术-10.装饰(Decorator)模式

    职责 装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对 ...

  3. 设计模式(三)装饰者模式Decorator

    装饰者模式针对的问题是:对一个结构已经确定的类,在不改变该类的结构的情况下,动态增加一些功能. 一般来说,都是对一些已经写好的架构增加自己的功能,或者应对多种情况,增加功能. 我们还是来玩一句红警,首 ...

  4. 设计模式之美:Role Object(角色对象)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Role Object 的示例实现. 意图 通过明确地附加角色对象到目标对象中,以使对象可以适配不同的客户需求.每个角色对象都代 ...

  5. 设计模式之美:Structural Patterns(结构型模式)

    结构型模式涉及到如何组合类和对象以获得更大的结构. 结构型类模式采用继承机制来组合接口实现. 结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法. 因为 ...

  6. 设计模式之美:Extension Object(扩展对象)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):使用示例结构实现 Extension Object. 实现方式(二):使用泛型实现 IExtensibleObject<T ...

  7. 设计模式之美:Proxy(代理)

    索引 别名 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):使用相同 Subject 接口实现 Proxy. 别名 Surrogate 意图 为其他对象提供一种代理以控制对这个对象的 ...

  8. 设计模式之美:Composite(组合)

    索引 意图 结构 参与者 适用性 缺点 效果 相关模式 实现 实现方式(一):在 Component 中定义公共接口以保持透明性但损失安全性. 意图 将对象组合成树形结构以表示 “部分-整体” 的层次 ...

  9. 设计模式之美:Adapter(适配器)

    索引 别名 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):简单直接的对象适配器. 实现方式(二):实现双向类适配器. 别名 包装器(Wrapper) 意图 将一个类的接口转换成客户 ...

随机推荐

  1. C# 集合与泛型

    一.古典集合方式 在C#2.0的时候集合主要通过两种方式实现: 1.使用ArrayList实现 新建ArrayList,然后将所有对象放入该数组中,简单直接,但缺点是该数组什么类型的元素都能接收,在实 ...

  2. ---Under Ubuntu 14.04

    Thinprint provides driver-free printing. Do you wish to enable this feature? [yes] Disabling timer-b ...

  3. information_schema系列二(列,列权限,事件,存储引擎)

    这个系列的文章主要是为了能够让自己了解MySQL5.7的一些系统表,统一做一下备注和使用,也希望分享出来让大家能够有一点点的受益. 1:COLUMNS 老规矩.查一下这个表,看一下记录,由于这个是看表 ...

  4. JAXB 2.0 API is being loaded from the bootstrap classloader

    在使用webservice,mule esb等需要jaxb的项目里经常会出现 JAXB 2.0 API is being loaded from the bootstrap classloader这个 ...

  5. hdu 1797 靠谱的算法应该是最大生成树,但是本人用最大流做的

    Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 22294   Accepted:  ...

  6. jQuery触发<a>标签的点击事件无效

    <a id="workFrame" href="pages/work.html" target="FrameBox">首页< ...

  7. EF联合查询的新用法

    用EF很多年了,做联合查询时,只知道linq和lambda两种语法,今天朋友发了一个链接,打开看后发现是EF内置的新的关于联合查询的方法,赶紧抄录下来,以备后用. 现在先把这几种方法,各写一个例子,便 ...

  8. oracle 创建数据表空间和用户

    --创建临时表空间(不必须)create temporary tablespace zwtest tempfile 'D:\Java\oracle\oradata\zwtest.dbf' size 5 ...

  9. sqlserver 分区表

    我们知道很多事情都存在一个分治的思想,同样的道理我们也可以用到数据表上,当一个表很大很大的时候,我们就会想到将表拆 分成很多小表,查询的时候就到各个小表去查,最后进行汇总返回给调用方来加速我们的查询速 ...

  10. 单片机TM4C123学习(十):ADC采样模块

    1.头文件 #include "tiva_adc.h" // ADC 2.引脚 3.初始化 // ADC初始化 // 光敏电阻(PE0)为通道3,存在序列0中,硬件平均为8个点 a ...