设计模式-09.DECORATOR(装饰)— 对象结构型模式

1 意图

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

2 别名

包装器 Wrapper

3 动机

希望给某个对象而不是整个类添加一些功能。如图形界面添加一些特性(边框,滚动等)。

  • 使用继承机制是以一种有效途径,然而不够灵活;
  • 将组件嵌入另一个对象,有这个对象添加特性,该嵌入的对象称为装饰。该装饰与所装饰的组件接口一致,故对其透明。

图一
图二

4 适用性

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

5 结构

图三

6 参与者

  • Component(VisualComponent)
    • 定义一个对象接口,可以给这些对象动态地添加职责。
  • ConcreteComponent(TextView)
    • 定义一个对象,可以给这个对象添加一些职责。
  • Decorator
    • 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
  • ConcreteDecorator(BorderDecorator,ScrollDecorator)
    • 向组件添加职责。

7 协作

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

8 效果

  • 优点:
    • 比静态继承更灵活
    • 避免在层次结构高层的类有太多的特征
  • 缺点:
    • Decorator 与 Component 不同,故使用 Decorator 不应该依赖 Component
    • 有许多小对象

9 实现

  • 接口的一致性;
  • 省略抽象的 Decorator 类,仅需要一个职责时;
  • 保存 Component 类的简单性;
  • 改变对象外壳(Strategy 策略模式可改变对象内核)

注:当 Component 类原本很庞大时,使用 Decorator 模式代价太大,可考虑使用 Strategy 模式。
图五

10 代码示例

  • Component

    1
    2
    3
    4
    class Component
    {
    public abstract void Operation();
    }
  • ConcreteComponent

    1
    2
    3
    4
    5
    6
    7
    class ConcreteComponent:Component
    {
    public override void Operation()
    {
    Console.WriteLine("ConcreteComponent");
    }
    }
  • BaseDecorator

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class BaseDecorator:Component
    {
    private Component component;

    public BaseDecorator(Component component)
    {
    this.component = component;
    }

    public override void Operation()
    {
    if(component!=null)
    {
    component.Operation();
    }
    }
    }
  • ConcreteDecorator

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class ConcreteDecorator:BaseDecorator
    {
    public ConcreteDecorator(Component component)
    :base(component)
    {

    }

    public override void Operation()
    {
    base.Operation();
    this.Draw();
    }

    private void Draw()
    {
    Console.WriteLine("ConcreteDecorator");
    }
    }
  • Client

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Client
    {
    public static void Main(string[] args)
    {
    Component component=new ConcreteComponent();
    component.Operation();

    BaseDecorator decorator=new ConcreteDecorator(component);
    decorator.Operation();
    }
    }

11 已知应用

用户界面工具,Stream。
图四

12 相关模式

  • Adapter 模式:Decorator 模式不同于 Adapter 模式,因为装饰仅改变对象的职责而不改
    变它的接口;而适配器将给对象一个全新的接口。
  • Composite 模式:可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅
    给对象添加一些额外的职责—它的目的不在于对象聚集。
  • Strategy 模式:用一个装饰你可以改变对象的外表;而Strategy模式使得你可以改变
    对象的内核。这是改变对象的两种途径。
坚持原创技术分享,您的支持将鼓励我继续创作!