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设计模式——装饰者模式
一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...
随机推荐
- mysql数据库 主从同步
我们知道mysql数据库为了得到更高性能,一般会读写分离.主库用于写操作,比如用于执行的insert.update操作:从库用于读,也就是常见的select操作. 写数据都在主库(master)操作, ...
- Qt编写物联网管理平台40-类型种类
一.前言 为了增强本系统的拓展性,做成通用的物联网管理平台,特意将控制器主设备类型.探测器子设备类型.对应种类符号等信息,全部做成表格可自定义添加和修改,这样在控制器信息表和探测器信息表管理的时候,可 ...
- 在线标定新思路!SST-Calib:最新Camera-Lidar时空同步标定算法(ITSC 2022)
在线标定新思路!SST-Calib:最新Camera-Lidar时空同步标定算法(ITSC 2022) 论文链接: 链接:https://pan.baidu.com/s/1qsfml4THs26Y7b ...
- vue辅助函数mapState和mapGetter前面三个点到底是什么意思:对象展开运算符
import store from "./store" computed: { useName: function() { return store.state.userName ...
- [转]使用Unity进行3D开发的思路和主要技术优势
此处直接附上别人撰写好的博文,分享给各位读者. 原文链接:Unity3D手游开发实践--<腾讯桌球:客户端总结>.
- 字符编码技术专题(一):快速理解ASCII、Unicode、GBK和UTF-8
本文由阮一峰(ruanyifeng.com)分享,本文收录时有内容修订和排版优化. 1.引言 今天中午,我突然想搞清楚 Unicode 和 UTF-8 之间的关系,就开始查资料. 这个问题比我想象的复 ...
- IM跨平台技术学习(四):蘑菇街基于Electron开发IM客户端的技术实践
本文由蘑菇街前端技术团队分享,原题"Electron 从零到一",有修订和改动. 1.引言 本系列文章的前面几篇主要是从Electron技术本身进行了讨论(包括:第1篇初步了解El ...
- Verilog4_时序逻辑电路
时序逻辑电路概述 时序逻辑电路分类: 按照触发器的动作特点: 同步时序逻辑电路: 所有触发器的状态变化都是在同一个时钟信号作用下同时发生的 异步时序逻辑电路: 没有统一的时钟脉冲信号,各触发器状态的变 ...
- Solution Set -「NOIP Simu.」20221111
\(\mathscr{A}\sim\) 遗忘十字路 Cover:「CF 1746D」Paths on the Tree. Tag:「C.性质/结论」 最原始的思路自然是 DP. 令 \(f ...
- Java内存模型深度剖析
为什么要有内存模型 在介绍Java内存模型之前,先来看一下到底什么是计算机内存模型,然后再来看Java内存模型在计算机内存模型的基础上做了哪些事情.要说计算机的内存模型,就要说一下一段古老的历史,看 ...