Java 设计模式:装饰者模式(Decorator Pattern)

简介: 装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。

一、模式定义

装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。

二、核心角色

  1. Component(组件接口)

    • 定义被装饰对象的公共接口
  2. ConcreteComponent(具体组件)

    • 实现基础功能的具体类
  3. Decorator(装饰者基类)

    • 持有Component引用,实现Component接口
  4. ConcreteDecorator(具体装饰者)

    • 添加具体装饰功能的实现类

三、经典实现(咖啡店订单系统)

// 1. 组件接口
public interface Coffee {
    String getDescription();
    double cost();
}

// 2. 具体组件
public class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "Simple Coffee";
    }

    @Override
    public double cost() {
        return 1.0;
    }
}

// 3. 装饰者基类
public abstract class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }

    @Override
    public double cost() {
        return decoratedCoffee.cost();
    }
}

// 4. 具体装饰者
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", Milk";
    }

    @Override
    public double cost() {
        return super.cost() + 0.5;
    }
}

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

    @Override
    public String getDescription() {
        return super.getDescription() + ", Mocha";
    }

    @Override
    public double cost() {
        return super.cost() + 0.7;
    }
}

// 5. 客户端使用
public class CoffeeShop {
    public static void main(String[] args) {
        Coffee order = new SimpleCoffee();
        System.out.println(order.getDescription() + " $" + order.cost());

        order = new MilkDecorator(order);
        System.out.println(order.getDescription() + " $" + order.cost());

        order = new MochaDecorator(order);
        System.out.println(order.getDescription() + " $" + order.cost());
    }
}

四、模式结构UML

           _________________________
          |        Component        |
          |-------------------------|
          | + getDescription()      |
          | + cost()                |
          |_________________________|
                     ▲
          ___________|___________
         |                       |
 _________▼_________       ______▼_______
| ConcreteComponent |     |   Decorator  |
|-------------------|     |--------------|
| + getDescription()|     | - component  |
| + cost()          |     |______________|
|___________________|              ▲
                           _________|_________
                          |                   |
                   _______▼_______     _______▼_______
                  | ConcreteDecoratorA |   | ConcreteDecoratorB |
                  |--------------------|   |--------------------|
                  | + addedBehavior()  |   | + addedBehavior()  |
                  |____________________|   |____________________|

五、模式优劣分析

优势:

  • 动态扩展功能,比继承更灵活
  • 符合开闭原则,无需修改现有代码
  • 支持多层嵌套装饰
  • 不同装饰类可自由组合

劣势:

  • 多层装饰增加代码复杂度
  • 装饰顺序影响最终结果
  • 可能产生大量小类
  • 调试困难(需逐层检查装饰)

六、应用场景

  1. 动态扩展对象功能
    (如为图形界面组件添加边框、滚动条)
  2. 撤销功能实现
    (通过装饰记录操作历史)
  3. 数据流处理
    (Java I/O中的缓冲、加密处理)
  4. 权限控制
    (通过装饰添加权限校验层)
  5. 日志记录
    (为业务逻辑添加日志装饰)

七、Java标准库应用

Java I/O流典型实现:

// 多层装饰示例
InputStream in = new FileInputStream("data.txt");
in = new BufferedInputStream(in);      // 添加缓冲功能
in = new GZIPInputStream(in);          // 添加解压缩功能
in = new Base64InputStream(in);        // 添加Base64解码

// 自定义装饰者示例
class UppercaseInputStream extends FilterInputStream {
    public UppercaseInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        int c = super.read();
        return (c == -1) ? c : Character.toUpperCase(c);
    }
}

八、高级应用技巧

透明性控制
通过接口继承保持装饰透明性:

interface Window {
    void draw();
}

class BasicWindow implements Window { /*...*/ }

abstract class WindowDecorator implements Window {
    protected Window window;
    // 不暴露额外方法
}

装饰顺序控制
使用建造者模式管理装饰顺序:

public class CoffeeBuilder {
    private Coffee coffee = new SimpleCoffee();

    public CoffeeBuilder addMilk() {
        coffee = new MilkDecorator(coffee);
        return this;
    }

    public Coffee build() {
        return coffee;
    }
}

动态移除装饰
实现装饰栈管理:

public class UndoableCoffee implements Coffee {
    private Deque<Coffee> stack = new ArrayDeque<>();

    public UndoableCoffee(Coffee coffee) {
        stack.push(coffee);
    }

    public void addDecorator(CoffeeDecorator decorator) {
        stack.push(decorator);
    }

    public void undo() {
        if (stack.size() > 1) {
            stack.pop();
        }
    }

    // 实现Coffee接口方法...
}

九、最佳实践建议

  1. 保持组件接口简洁
    避免装饰者需要实现过多无关方法
  2. 控制装饰层次深度
    建议不超过4层装饰
  3. 优先使用透明装饰
    保持装饰前后接口一致
  4. 注意线程安全问题
    对于可变状态装饰器,使用同步控制
  5. 性能敏感场景慎用
    多层装饰可能影响性能(建议结合对象池)
相关文章
|
4月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
508 2
|
4月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
450 0
|
6月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
4月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
607 35
|
4月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
411 8
|
6月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
6月前
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
9月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
279 16
|
9月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
265 0
|
9月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
280 0