一、模式定义

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

二、核心角色

  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. 性能敏感场景慎用

    多层装饰可能影响性能(建议结合对象池)

Java 设计模式:装饰者模式(Decorator Pattern)的更多相关文章

  1. 设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法

    装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716 ...

  2. 浅谈设计模式--装饰者模式(Decorator Pattern)

    挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...

  3. 设计模式 - 装饰者模式(Decorator Pattern) 具体解释

    装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...

  4. Java设计模式——装饰器模式(Decorator)

    今天上课讲了java设计模式中的装饰器模式--Decorator,由于早上起的很早,肚子也很饿,知识点本身也晦涩难懂,听的云里雾里的,所以在课下对这块的知识做出一些总结. 定义 装饰器模式又名包装(W ...

  5. C#设计模式——装饰者模式(Decorator Pattern)

    一.例子在软件开发中,我们往往会想要给某一类对象增加不同的功能.比如要给汽车增加ESP.天窗或者定速巡航.如果利用继承来实现,就需要定义无数的类,Car,ESPCar,CCSCar,SunRoofCa ...

  6. 设计模式学习--装饰者模式(Decorator Pattern)

    概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...

  7. JAVA设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

  8. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  9. 【设计模式】Java设计模式 - 装饰者模式

    Java设计模式 - 装饰者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自 ...

  10. 从源码角度理解Java设计模式——装饰者模式

    一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...

随机推荐

  1. Qt音视频开发5-vlc事件订阅

    一.前言 事件订阅可以拿到文件长度.播放进度.播放状态改变等信息,vlc的事件订阅机制封装的比较友好,只需要先创建一个事件管理器,然后逐个订阅自己感兴趣的需要的事件,不感兴趣的可以不要订阅,只有订阅了 ...

  2. IntelliJ IDEA 2020+Maven+SSM框架正常编译并与行后端代码时控制台的提示信息

  3. Eclipse中如何快速查询一个类和方法在哪里被引用?

    0.在Eclipse中使用全局搜索Ctrl+h的方法快速查询一个类在哪里被引用. 打开Eclipse,使用快捷键Ctrl+h,会弹出一个对话框,找到File Search页签,在Containing ...

  4. docker和主机之间文件传输

    docker和主机之间文件传输 1.从docker内部向主机传输文件 语法: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- 示例:将容器96f7 ...

  5. BOF编写-修改时间戳

    模板配置 跟着网上的教程使用evilashz师傅的模板,下载模板解压至vs的模板目录: %UserProfile%\Documents\Visual Studio 2022\Templates\Pro ...

  6. Solution Set -「LOCAL」冲刺省选 Round I

    \(\mathscr{Summary}\)   状态还行叭.   A 题又犯坏习惯,走起来就大力分讨,上了个厕所之后冷静一下开始寻找比较普适性的 DP 状态,然后几乎就切掉了,可惜复杂度写假了没发现( ...

  7. 分布式数据库NoSQL简介

    NoSQL第一部分   一.什么是NoSQL? 问题:12306在开始诞生的前几年,每到重大节假日,经常"瘫痪",直接原因就是集中超负荷的访问量.技术原因是它在此期间所采用的国际著 ...

  8. Golang-容器3

    http://c.biancheng.net/golang/container/ Go语言数组详解 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成.因为数组的长度是固定 ...

  9. 第一二章(Nginx+Lua)开发环境

    第一章 安装OpenResty(Nginx+Lua)开发环境 首先我们选择使用OpenResty,其是由Nginx核心加很多第三方模块组成,其最大的亮点是默认集成了Lua开发环境,使得Nginx可以作 ...

  10. YUV 格式

    1. YUV比例 分三种:YUV44,YUV422,YUV420 2. YUV排布 分三种:YUV planar,YUV Semi-Plannar,YUV packed 以YUV422 8*4 为例 ...