一、模式定义

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

二、核心角色

  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. 聊一聊 C#线程池 的线程动态注入 (中)

    一:背景 1. 讲故事 上一篇我们用 Thread.Sleep 的方式演示了线程池饥饿场景下的动态线程注入,可以观察到大概 1s 产生 1~2 个新线程,很显然这样的增长速度扛不住上游请求对线程池的D ...

  2. Qt编写地图综合应用19-地图服务

    一.前言 国内提供地图服务的厂家基本上是五家,百度地图.高德地图.腾讯地图.搜狗地图.天地图,国外的一般还有谷歌地图.微软地图(BING地图),这几家的地图服务的api接口都大同小异,甚至很多函数的名 ...

  3. Qt编写地图综合应用17-地址经纬度互转

    一.前言 地址和经纬度互相转换的功能也经常用到,比如上次的路线方案查询的功能,之前官网是提供了直接输入出发地点和目的地的中文汉字,就可以查询到最优的路线,后面只支持输入出发地点和目的地的经纬度坐标了, ...

  4. Qt编写的项目作品33-斗图神器(雨田哥作品)

    一.功能特点 支持HTTP,HTTPS网络表情图片下载,本地缓存. 采用MV模式,支持大量图片表情预览查看. 采用多线程异步下载图片刷新. 图片搜索功能(因网络提供API无信息字段提供,占搜索不了.但 ...

  5. IDEA中导入其它由Maven管理的java web项目并运行,提示“Error:(3, 38) java: 程序包org.springframework.stereotype不存在”问题的解决

    现象描述: IDEA中导入其它由Maven管理的java web项目并运行,提示"Error:(3, 38) java: 程序包org.springframework.stereotype不 ...

  6. 长连接网关技术专题(四):爱奇艺WebSocket实时推送网关技术实践

    本文由爱奇艺技术团队原创分享,原题<构建通用WebSocket推送网关的设计与实践>,有优化和改动. 1.引言 丛所周之,HTTP协议是一种无状态.基于TCP的请求/响应模式的协议,即请求 ...

  7. 神仙打架的一期「GitHub 热点速览」

    由于上周出月刊「GitHub 热点速览」断更了一期,本期攒了两周的热门开源项目,真可谓是神仙打架! 这两天开源的大模型 DeepSeek-V3 凭借极低的训练成本和出色的评测表现,迅速出圈.开源仅 5 ...

  8. PaperAssistant:使用Microsoft.Extensions.AI实现

    前言 上篇文章介绍了使用Semantic Kernel Chat Completion Agent实现的版本. 使用C#构建一个论文总结AI Agent 今天来介绍一下使用Microsoft.Exte ...

  9. Python学习(一)——配套《PyTorch深度学习实战》

    记录一下Python学习过程中的一些问题: 1. 在JupyterLab中查询当前文件的地址 import os print(os.getcwd()) #查询该文件的地址 2. 新建cell 在 Ju ...

  10. 学Shiro完结版-5

    第二十一章 授予身份及切换身份--<跟我学Shiro> 在一些场景中,比如某个领导因为一些原因不能进行登录网站进行一些操作,他想把他网站上的工作委托给他的秘书,但是他不想把帐号/密码告诉他 ...