结构型设计模式的一种

【DP】定义

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

使用场景

  1. 已有功能只能满足部分需求,需要在已有功能基础上动态增加功能,使用装饰器可以将核心功能和装饰功能从逻辑上区分开
  2. 有一个动作执行链,需要指定先做什么,后做什么

类图

装饰器模式类图
核心是装饰器继承已有功能接口,并使用已有功能接口,这样就可以实现按顺序装饰。
AbstractDecrator类是抽象类,根据需求选择是否需要该类。

举例

有一个场景: 平台部门写了公共打印的功能,但是业务部门A需要在打印前增加打印人,业务部门B除了要在打印前增加打印人,还需要在打印后增加打印时间。

公共打印接口和实现类如下:

1
2
3
4
5
6
7
8
9
10
public interface IPrint {
void print();
}

public class PlatformPrint implements IPrint {
@Override
public void print() {
System.out.println("Platform print......");
}
}

业务部门A需要给公共接口增加动作,那么A可以增加装饰器如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class APrint implements IPrint{
// 要装饰的对象
private IPrint print;
// 装饰动作
public void decorate(IPrint print) {
this.print = print;
}
@Override
public void print() {
// 打印前增加打印人
System.out.println("Printer: abcd");
// 执行被装饰对象的方法
print.print();
}
}

业务部门B也需要增加动作,但是可以在A的基础上增加即可,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class BPrint implements IPrint {
// 要装饰的对象
private IPrint print;
// 装饰动作
public void decorate(IPrint print) {
this.print = print;
}
@Override
public void print() {
// 执行被装饰对象的方法
print.print();
// 打印后增加打印时间
System.out.println("Print time : 2019-04-02");
}
}

那么,在使用时,就可以如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
public static void main() {
// 平台打印
IPrint print = new PlatformPrint();
// 业务A打印
APrint aPrint = new APrint();
// 业务A装饰平台打印类
aPrint.decorate(print);
aPrint.print();

// 业务B打印
BPrint bPrint = new BPrint();
// 业务B装饰业务A打印类
bPrint.decorate(aPrint);
bPrint.print();
}
}

注意事项

  1. 装饰器的功能最好分开