设计模式-结构型-装饰器模式(Decorator)
参考文献
装饰器模式
- 此模式的目的是向对象动态添加额外的职责.
组件
- 抽象组件(
Component
): 定义了被装饰对象的接口,可以是抽象类或接口.它通常声明了核心的操作方法. - 具体组件(
ConcreteComponent
): 实现了抽象组件接口,是被装饰的原始对象.具体组件是装饰器模式的核心. - 抽象装饰器(
Decorator
): 也是抽象组件的实现类,它持有一个抽象组件对象作为成员变量,并通过构造函数或setter方法进行注入. - 具体装饰器(
ConcreteDecorator
): 继承自抽象装饰器,实现了抽象组件的接口,并在其中添加额外的功能.具体装饰器可以对抽象组件进行装饰,即包装一个具体组件对象,并在调用核心功能方法前后增加额外的行为.
实现方式
-
定义抽象组件(
Component
)接口,声明需要被装饰的核心功能方法.1
2
3interface Report {
void generate();
} -
创建具体组件(ConcreteComponent)类,实现抽象组件接口,提供基本的功能.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class PDFReport implements Report {
public void generate() {
System.out.println("生成 PDF 报告");
}
}
class HTMLReport implements Report {
public void generate() {
System.out.println("生成 HTML 报告");
}
}
class ExcelReport implements Report {
public void generate() {
System.out.println("生成 Excel 报告");
}
} -
创建抽象装饰器(
Decorator
)类,实现抽象组件接口,并持有一个抽象组件对象作为成员变量.1
2
3
4
5
6
7
8
9
10
11abstract class ReportDecorator implements Report {
protected Report decoratedReport;
public ReportDecorator(Report decoratedReport) {
this.decoratedReport = decoratedReport;
}
public void generate() {
decoratedReport.generate();
}
} -
创建具体装饰器(
ConcreteDecorator
)类,继承抽象装饰器类,并在其中重写核心功能方法,并可选择在调用前后增加额外的功能.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
47class EncryptionDecorator extends ReportDecorator {
public EncryptionDecorator(Report decoratedReport) {
super(decoratedReport);
}
public void generate() {
decoratedReport.generate();
encryptReport();
}
private void encryptReport() {
System.out.println("对报告进行加密");
}
}
class CompressionDecorator extends ReportDecorator {
public CompressionDecorator(Report decoratedReport) {
super(decoratedReport);
}
public void generate() {
decoratedReport.generate();
compressReport();
}
private void compressReport() {
System.out.println("对报告进行压缩");
}
}
class WatermarkDecorator extends ReportDecorator {
public WatermarkDecorator(Report decoratedReport) {
super(decoratedReport);
}
public void generate() {
decoratedReport.generate();
addWatermark();
}
private void addWatermark() {
System.out.println("给报告添加水印");
}
} -
在客户端中,使用具体组件来创建对象,并根据需要使用具体装饰器来装饰对象.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class ReportGenerator {
public static void main(String[] args) {
// 创建具体的报告对象
Report pdfReport = new PDFReport();
Report htmlReport = new HTMLReport();
// 对报告进行装饰
Report encryptedPDFReport = new EncryptionDecorator(pdfReport);
Report compressedHTMLReport = new CompressionDecorator(htmlReport);
Report encryptedCompressedExcelReport = new EncryptionDecorator(new CompressionDecorator(new ExcelReport()));
// 生成报告
pdfReport.generate();
System.out.println("-----------");
encryptedPDFReport.generate();
System.out.println("-----------");
compressedHTMLReport.generate();
System.out.println("-----------");
encryptedCompressedExcelReport.generate();
}
}
使用场景
- 在不修改现有对象结构的情况下,为对象添加新的行为或属性.
- 需要动态地对对象进行功能扩展,且可以灵活地组合各种功能.
- 需要透明地、无限级地对对象进行包装和扩展.
- 需要将功能的复杂性与核心业务逻辑相分离,使其更易于维护和理解.
- 实际使用场景
Java IO
库中的流操作,如BufferedInputStream、DataInputStream
等.GUI
中的界面元素样式装饰,如按钮的边框、背景等.- 日志记录器的包装,如记录日志到文件、输出日志到控制台等.
- 数据加密和压缩.
- 适配器模式侧重于转换,而装饰模式侧重于动态扩展;桥接模式侧重于横向宽度的扩展,而装饰模式侧重于纵向深度的扩展
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!