设计模式-装饰器模式

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

设计模式-概述

结构

装饰器模式类似于继承的关系, 但是比继承更加灵活, 它有如下角色:

  1. 抽象构件(Component)
  2. 具体构件(ConcreteComponent)
  3. 抽象的装饰(Decorator)
  4. 具体的装饰(ConcreteDecorate)

decorate-1.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@startuml decorate-1
!include common.cuml

Interface(Component,"抽象构件") {
+ operation() : void
}

Class(ConcreteComponent,"具体构件") {
+ operation() : void
}

Class(Decorator,"抽象装饰") {
- component : Component
+ Decorator(Component : Strategy) : void
+ operation() : void
}

Class(ConcreteDecoratorA,"具体装饰A") {
+ operation() : void
}

Class(ConcreteDecoratorB,"具体装饰B") {
+ operation() : void
}

note as N1
public void operation() {
component.operation();
}
end note

note as NA
public void operation() {
// todo A自己的处理逻辑a
super.operation();
// todo A自己的处理逻辑b
}
end note

note as NB
public void operation() {
// todo B自己的处理逻辑a
super.operation();
// todo B自己的处理逻辑b
}
end note

ConcreteDecoratorA ..up.. NA
ConcreteDecoratorB ..up.. NB
Decorator ... N1
ConcreteDecoratorA --|> Decorator
ConcreteDecoratorB --|> Decorator
Decorator ..|> Component
ConcreteComponent ..|> Component
Component --o Decorator

@enduml

代码实现

  1. 有一个组件 Component, 执行 operation() 方法, 输出ConcreteComponent.operation.
  2. ConcreteDecoratorA 包装了一下 Component, 执行其 operation() 方法, 输出如下:
    1
    2
    3
    ConcreteDecoratorA.operation before
    ConcreteComponent.operation
    ConcreteDecoratorA.operation after
  3. ConcreteDecoratorB 包装了一下 ConcreteDecoratorA, 执行其 operation() 方法, 输出如下:
    1
    2
    3
    4
    5
    ConcreteDecoratorB.operation before
    ConcreteDecoratorA.operation before
    ConcreteComponent.operation
    ConcreteDecoratorA.operation after
    ConcreteDecoratorB.operation after

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.yuda.test;

public class DecoratorPattern {
public static void main(String[] args) {
Component component = new ConcreteComponent();
component.operation();
System.out.println("=======================================");
Component decoratedComponent = new ConcreteDecoratorA(component);
decoratedComponent.operation();
System.out.println("=======================================");
Component decoratedComponentB = new ConcreteDecoratorB(decoratedComponent);
decoratedComponentB.operation();
}
}

interface Component {
public void operation();
}

class ConcreteComponent implements Component {

@Override
public void operation() {
System.out.println("ConcreteComponent.operation");
}
}

abstract class Decorator implements Component {
private Component component;

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

@Override
public void operation() {
component.operation();
}
}

class ConcreteDecoratorA extends Decorator {

public ConcreteDecoratorA(Component component) {
super(component);
}

@Override
public void operation() {
System.out.println("ConcreteDecoratorA.operation before");
super.operation();
System.out.println("ConcreteDecoratorA.operation after");
}
}

class ConcreteDecoratorB extends Decorator {

public ConcreteDecoratorB(Component component) {
super(component);
}

@Override
public void operation() {
System.out.println("ConcreteDecoratorB.operation before");
super.operation();
System.out.println("ConcreteDecoratorB.operation after");
}
}

使用场景

  1. 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
  2. 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
  3. 当对象的功能要求可以动态地添加,也可以再动态地撤销时。

具体应用

  1. jdk中关于 I/O 的标准库, 例如:InputStream, FilterInputStream
    jdk_io.jpg

  2. 在Spring中, 处理与Spring管理缓存同步事务的相关类中可找到 org.springframework.cache.transaction.TransactionAwareCacheDecoratororg.springframework.cache.Cache.

    1
    2
    3
    4
    5
    6
    7
    8
    public class TransactionAwareCacheDecorator implements Cache {
    private final Cache targetCache;
    public TransactionAwareCacheDecorator(Cache targetCache) {
    Assert.notNull(targetCache, "Target Cache must not be null");
    this.targetCache = targetCache;
    }
    // ..... 略
    }