一、模式定义

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

二、核心角色

  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. mysql数据库 主从同步

    我们知道mysql数据库为了得到更高性能,一般会读写分离.主库用于写操作,比如用于执行的insert.update操作:从库用于读,也就是常见的select操作. 写数据都在主库(master)操作, ...

  2. Qt编写物联网管理平台40-类型种类

    一.前言 为了增强本系统的拓展性,做成通用的物联网管理平台,特意将控制器主设备类型.探测器子设备类型.对应种类符号等信息,全部做成表格可自定义添加和修改,这样在控制器信息表和探测器信息表管理的时候,可 ...

  3. 在线标定新思路!SST-Calib:最新Camera-Lidar时空同步标定算法(ITSC 2022)

    在线标定新思路!SST-Calib:最新Camera-Lidar时空同步标定算法(ITSC 2022) 论文链接: 链接:https://pan.baidu.com/s/1qsfml4THs26Y7b ...

  4. vue辅助函数mapState和mapGetter前面三个点到底是什么意思:对象展开运算符

    import store from "./store" computed: { useName: function() { return store.state.userName ...

  5. [转]使用Unity进行3D开发的思路和主要技术优势

    此处直接附上别人撰写好的博文,分享给各位读者. 原文链接:Unity3D手游开发实践--<腾讯桌球:客户端总结>.

  6. 字符编码技术专题(一):快速理解ASCII、Unicode、GBK和UTF-8

    本文由阮一峰(ruanyifeng.com)分享,本文收录时有内容修订和排版优化. 1.引言 今天中午,我突然想搞清楚 Unicode 和 UTF-8 之间的关系,就开始查资料. 这个问题比我想象的复 ...

  7. IM跨平台技术学习(四):蘑菇街基于Electron开发IM客户端的技术实践

    本文由蘑菇街前端技术团队分享,原题"Electron 从零到一",有修订和改动. 1.引言 本系列文章的前面几篇主要是从Electron技术本身进行了讨论(包括:第1篇初步了解El ...

  8. Verilog4_时序逻辑电路

    时序逻辑电路概述 时序逻辑电路分类: 按照触发器的动作特点: 同步时序逻辑电路: 所有触发器的状态变化都是在同一个时钟信号作用下同时发生的 异步时序逻辑电路: 没有统一的时钟脉冲信号,各触发器状态的变 ...

  9. Solution Set -「NOIP Simu.」20221111

    \(\mathscr{A}\sim\) 遗忘十字路   Cover:「CF 1746D」Paths on the Tree.   Tag:「C.性质/结论」   最原始的思路自然是 DP. 令 \(f ...

  10. Java内存模型深度剖析

    为什么要有内存模型  在介绍Java内存模型之前,先来看一下到底什么是计算机内存模型,然后再来看Java内存模型在计算机内存模型的基础上做了哪些事情.要说计算机的内存模型,就要说一下一段古老的历史,看 ...