Java 设计模式:装饰者模式(Decorator Pattern)
一、模式定义
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
二、核心角色
Component(组件接口)
- 定义被装饰对象的公共接口
ConcreteComponent(具体组件)
- 实现基础功能的具体类
Decorator(装饰者基类)
- 持有Component引用,实现Component接口
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() |
|____________________| |____________________|
五、模式优劣分析
优势:
- 动态扩展功能,比继承更灵活
- 符合开闭原则,无需修改现有代码
- 支持多层嵌套装饰
- 不同装饰类可自由组合
劣势:
- 多层装饰增加代码复杂度
- 装饰顺序影响最终结果
- 可能产生大量小类
- 调试困难(需逐层检查装饰)
六、应用场景
- 动态扩展对象功能
(如为图形界面组件添加边框、滚动条) - 撤销功能实现
(通过装饰记录操作历史) - 数据流处理
(Java I/O中的缓冲、加密处理) - 权限控制
(通过装饰添加权限校验层) - 日志记录
(为业务逻辑添加日志装饰)
七、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接口方法...
}
九、最佳实践建议
- 保持组件接口简洁
避免装饰者需要实现过多无关方法 - 控制装饰层次深度
建议不超过4层装饰 - 优先使用透明装饰
保持装饰前后接口一致 - 注意线程安全问题
对于可变状态装饰器,使用同步控制 - 性能敏感场景慎用
多层装饰可能影响性能(建议结合对象池)
Java 设计模式:装饰者模式(Decorator Pattern)的更多相关文章
- 设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法
装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716 ...
- 浅谈设计模式--装饰者模式(Decorator Pattern)
挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...
- 设计模式 - 装饰者模式(Decorator Pattern) 具体解释
装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...
- Java设计模式——装饰器模式(Decorator)
今天上课讲了java设计模式中的装饰器模式--Decorator,由于早上起的很早,肚子也很饿,知识点本身也晦涩难懂,听的云里雾里的,所以在课下对这块的知识做出一些总结. 定义 装饰器模式又名包装(W ...
- C#设计模式——装饰者模式(Decorator Pattern)
一.例子在软件开发中,我们往往会想要给某一类对象增加不同的功能.比如要给汽车增加ESP.天窗或者定速巡航.如果利用继承来实现,就需要定义无数的类,Car,ESPCar,CCSCar,SunRoofCa ...
- 设计模式学习--装饰者模式(Decorator Pattern)
概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...
- JAVA设计模式--装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...
- Java设计模式——装饰者模式
JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...
- 【设计模式】Java设计模式 - 装饰者模式
Java设计模式 - 装饰者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自 ...
- 从源码角度理解Java设计模式——装饰者模式
一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...
随机推荐
- Qt音视频开发5-vlc事件订阅
一.前言 事件订阅可以拿到文件长度.播放进度.播放状态改变等信息,vlc的事件订阅机制封装的比较友好,只需要先创建一个事件管理器,然后逐个订阅自己感兴趣的需要的事件,不感兴趣的可以不要订阅,只有订阅了 ...
- IntelliJ IDEA 2020+Maven+SSM框架正常编译并与行后端代码时控制台的提示信息
- Eclipse中如何快速查询一个类和方法在哪里被引用?
0.在Eclipse中使用全局搜索Ctrl+h的方法快速查询一个类在哪里被引用. 打开Eclipse,使用快捷键Ctrl+h,会弹出一个对话框,找到File Search页签,在Containing ...
- docker和主机之间文件传输
docker和主机之间文件传输 1.从docker内部向主机传输文件 语法: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- 示例:将容器96f7 ...
- BOF编写-修改时间戳
模板配置 跟着网上的教程使用evilashz师傅的模板,下载模板解压至vs的模板目录: %UserProfile%\Documents\Visual Studio 2022\Templates\Pro ...
- Solution Set -「LOCAL」冲刺省选 Round I
\(\mathscr{Summary}\) 状态还行叭. A 题又犯坏习惯,走起来就大力分讨,上了个厕所之后冷静一下开始寻找比较普适性的 DP 状态,然后几乎就切掉了,可惜复杂度写假了没发现( ...
- 分布式数据库NoSQL简介
NoSQL第一部分 一.什么是NoSQL? 问题:12306在开始诞生的前几年,每到重大节假日,经常"瘫痪",直接原因就是集中超负荷的访问量.技术原因是它在此期间所采用的国际著 ...
- Golang-容器3
http://c.biancheng.net/golang/container/ Go语言数组详解 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成.因为数组的长度是固定 ...
- 第一二章(Nginx+Lua)开发环境
第一章 安装OpenResty(Nginx+Lua)开发环境 首先我们选择使用OpenResty,其是由Nginx核心加很多第三方模块组成,其最大的亮点是默认集成了Lua开发环境,使得Nginx可以作 ...
- YUV 格式
1. YUV比例 分三种:YUV44,YUV422,YUV420 2. YUV排布 分三种:YUV planar,YUV Semi-Plannar,YUV packed 以YUV422 8*4 为例 ...