23种设计模式之装饰者模式

在这里插入图片描述

一、装饰者模式简介

1.1 定义


  装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地向对象添加新的功能,而不改变其结构和实现。装饰者模式通过组合来实现功能的扩展,它将功能划分成单一职责的类,并在需要时动态地组合这些功能实例化对象。

  根据《设计模式:可复用面向对象软件的基础》一书的定义,装饰者模式是:

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

1.2 模式类型


  结构型

1.3 主要作用


  1. 扩展功能:允许在运行时动态地给对象添加新的功能,而不需要修改对象的结构。这有助于遵循 OCP 原则。
  2. 灵活性和可重用性:装饰者模式通过创建装饰类来包裹原始对象,并在装饰类中添加功能,这样可以灵活组合不同的装饰器以达到不同的功能组合,同时原始类和装饰类都可以独立复用。
  3. 简化复杂度:对于有大量可选功能的对象,如果使用继承来实现每种可能的功能组合,会导致类的数量爆炸式增长。装饰者模式通过组合而非继承的方式来添加功能,大大减少了类的数量,简化了系统的复杂度。
  4. 保持接口一致性:装饰者模式保持了被装饰对象的接口一致,客户端代码可以透明地使用装饰后的对象,无需关心是否以及如何被装饰,这有利于代码的维护和扩展。
  5. 易于管理对象的责任:每个装饰者都负责单一职责,即添加特定的功能,这使得对象的责任更加清晰,便于管理和调试。

1.4 优点


  1. 灵活性高:可以在运行时任意组合装饰者,动态地扩展对象功能。
  2. 符合单一职责原则:每个装饰者类只负责增加一种功能,类的职责更加单一。
  3. 降低类复杂度:相比通过继承扩展功能,装饰者模式避免了大量的子类生成,从而减少类的复杂度。

1.5 缺点


  1. 对象数量增多:由于装饰者和被装饰者都是对象,这会增加系统中对象的数量,增加管理成本。
  2. 依赖过多:容易产生过多的小型对象,增加系统复杂性,理解和维护变得更加困难。

二、模式动机


装饰者模式的主要动机是应对以下几个问题:

  • 避免类爆炸:通过继承添加新功能会导致子类数量激增,维护起来十分困难。
  • 灵活组合功能:继承的组合方式是静态的,不够灵活。装饰者模式允许动态地组合功能。
  • 单一职责原则:通过将功能分解到不同的装饰类中,装饰者模式使每个类的职责更加单一,代码更易读易维护。

三、模式结构

在这里插入图片描述

装饰者模式通常涉及以下几个角色:

  • Component(抽象组件):定义一个对象接口,可以给这些对象动态地添加职责。
  • ConcreteComponent(具体组件):实现 Component 接口的具体对象,可以给这些对象添加一些职责。
  • Decorator(装饰者抽象类):继承 Component 接口,通常持有一个 Component 对象的引用,并定义一个与 Component 接口一致的接口。
  • ConcreteDecorator(具体装饰者):扩展 Decorator 类的具体装饰者,负责向组件添加新的职责。

四、 装饰者模式的实现


  我们将以一个具体的咖啡示例来介绍装饰者模式的实现。在这个例子中,我们有一个基本的咖啡对象,可以动态地添加不同的配料(如牛奶和糖)。

4.1 组件接口

// Java实现
public interface Coffee {
    double cost();
    String getDescription();
}

4.2 具体组件

public class SimpleCoffee implements Coffee {
    public double cost() {
        return 5.0;
    }
    
    public String getDescription() {
        return "Simple Coffee";
    }
}

4.3 装饰者抽象类

public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
    
    public double cost() {
        return coffee.cost();
    }
    
    public String getDescription() {
        return coffee.getDescription();
    }
}

4.4 具体装饰者

public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    public double cost() {
        return super.cost() + 1.5;
    }
    
    public String getDescription() {
        return super.getDescription() + ", Milk";
    }
}

public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    public double cost() {
        return super.cost() + 0.5;
    }
    
    public String getDescription() {
        return super.getDescription() + ", Sugar";
    }
}

4.5 使用装饰者模式

public class CoffeeShop {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());

        coffee = new MilkDecorator(coffee);
        System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());

        coffee = new SugarDecorator(coffee);
        System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());
    }
}

4.6 输出结果:

Simple Coffee Cost: $5.0
Simple Coffee, Milk Cost: $6.5
Simple Coffee, Milk, Sugar Cost: $7.0

五、 应用场景

在这里插入图片描述

5.1 图形用户界面


  在图形用户界面(GUI)框架中,装饰者模式广泛应用于实现各种控件的装饰功能。控件如按钮、文本框等可以用不同的装饰者类装饰来添加多种新功能,如滚动条、边框等。例如,Java Swing框架中的JComponent类就是使用类似装饰者模式的理念实现的。

5.2 数据流处理


  在数据流处理框架中,输入输出流是装饰者模式的另一个经典应用。JavaI/O流设计就是实现装饰者模式的一个优秀示例,如FileInputStreamBufferedInputStreamDataInputStream等通过装饰者模式组合,实现了灵活而强大的数据流操作功能。

5.3 日志功能


  日志记录功能的实现也是装饰者模式的理想应用场景。例如,传统的日志记录器Logger可以通过装饰者模式添加不同的日志处理和记录策略,如格式化日志、输出到文件、发送电子邮件等。

5.4 监控和计数


  在监控系统中,可以动态地为程序添加计数器、性能监控器等功能,以增强对系统运行状态的了解。

六、总结

  装饰者模式是一种强大的设计模式,它提供了一种灵活、可扩展的方式来动态地为对象添加新功能。通过这一模式,我们可以在不修改已有类代码的情况下,灵活地扩展系统功能,符合开闭原则单一职责原则。无论是在GUI编程中、日志功能增强,还是在数据流处理以及监控系统中,装饰者模式都能发挥重要作用。

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JAVA开发区

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值