参考文献

装饰器模式

  • 此模式的目的是向对象动态添加额外的职责.

组件

  • 抽象组件(Component): 定义了被装饰对象的接口,可以是抽象类或接口.它通常声明了核心的操作方法.
  • 具体组件(ConcreteComponent): 实现了抽象组件接口,是被装饰的原始对象.具体组件是装饰器模式的核心.
  • 抽象装饰器(Decorator): 也是抽象组件的实现类,它持有一个抽象组件对象作为成员变量,并通过构造函数或setter方法进行注入.
  • 具体装饰器(ConcreteDecorator): 继承自抽象装饰器,实现了抽象组件的接口,并在其中添加额外的功能.具体装饰器可以对抽象组件进行装饰,即包装一个具体组件对象,并在调用核心功能方法前后增加额外的行为.

实现方式

  • 定义抽象组件(Component)接口,声明需要被装饰的核心功能方法.

    1
    2
    3
    interface Report {
    void generate();
    }
  • 创建具体组件(ConcreteComponent)类,实现抽象组件接口,提供基本的功能.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class PDFReport implements Report {
    @Override
    public void generate() {
    System.out.println("生成 PDF 报告");
    }
    }

    class HTMLReport implements Report {
    @Override
    public void generate() {
    System.out.println("生成 HTML 报告");
    }
    }

    class ExcelReport implements Report {
    @Override
    public void generate() {
    System.out.println("生成 Excel 报告");
    }
    }
  • 创建抽象装饰器(Decorator)类,实现抽象组件接口,并持有一个抽象组件对象作为成员变量.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    abstract 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
    47
    class EncryptionDecorator extends ReportDecorator {
    public EncryptionDecorator(Report decoratedReport) {
    super(decoratedReport);
    }

    @Override
    public void generate() {
    decoratedReport.generate();
    encryptReport();
    }

    private void encryptReport() {
    System.out.println("对报告进行加密");
    }
    }

    class CompressionDecorator extends ReportDecorator {
    public CompressionDecorator(Report decoratedReport) {
    super(decoratedReport);
    }

    @Override
    public void generate() {
    decoratedReport.generate();
    compressReport();
    }

    private void compressReport() {
    System.out.println("对报告进行压缩");
    }
    }

    class WatermarkDecorator extends ReportDecorator {
    public WatermarkDecorator(Report decoratedReport) {
    super(decoratedReport);
    }

    @Override
    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
    21
    public 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中的界面元素样式装饰,如按钮的边框、背景等.
    • 日志记录器的包装,如记录日志到文件、输出日志到控制台等.
    • 数据加密和压缩.
  • 适配器模式侧重于转换,而装饰模式侧重于动态扩展;桥接模式侧重于横向宽度的扩展,而装饰模式侧重于纵向深度的扩展