Java 设计模式:装饰者模式(Decorator Pattern)

news/2025/3/14 15:56:43/文章来源:https://www.cnblogs.com/wxsw/p/18772230

一、模式定义

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

二、核心角色

  1. Component(组件接口)

    • 定义被装饰对象的公共接口
  2. ConcreteComponent(具体组件)

    • 实现基础功能的具体类
  3. Decorator(装饰者基类)

    • 持有Component引用,实现Component接口
  4. ConcreteDecorator(具体装饰者)

    • 添加具体装饰功能的实现类

三、经典实现(咖啡店订单系统)

// 1. 组件接口
public interface Coffee {String getDescription();double cost();
}// 2. 具体组件
public class SimpleCoffee implements Coffee {@Overridepublic String getDescription() {return "Simple Coffee";}@Overridepublic double cost() {return 1.0;}
}// 3. 装饰者基类
public abstract class CoffeeDecorator implements Coffee {protected final Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}@Overridepublic double cost() {return decoratedCoffee.cost();}
}// 4. 具体装饰者
public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Milk";}@Overridepublic double cost() {return super.cost() + 0.5;}
}public class MochaDecorator extends CoffeeDecorator {public MochaDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Mocha";}@Overridepublic 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);}@Overridepublic 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. 性能敏感场景慎用
    多层装饰可能影响性能(建议结合对象池)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/898703.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Ollama本地部署DeepSeek-r1:7b大语言模型

1、概述随着人工智能技术的飞速发展,越来越多的开发者和企业开始关注大语言模型(LLM)。这些模型以其强大的自然语言处理能力,在文本生成、问答、翻译、分类等多种任务中表现出色。然而,在实际使用中,许多人会遇到如何快速且高效地部署这些模型的问题。本文将介绍如何通过…

web116笔记(misc+lfi)

访问题目是一个视频,源码也没有什么有用信息 提示:misc+lfi 下载视频,使用 010editor 打开,发现存在 png 图片的数据,搜索另存为 过滤了蛮多的,不过没有过滤flag ,也没有过滤 filter 尝试构造语句?file=php://filter/resource=flag.php (直接读取) 如果没有设置 fil…

具身智能

Topic I: 3D VIsion Topic II: Robotics Topic IV: Reinforcement learning Linear Algebra Vector Space 向量空间Linear Combination 线性组合\(w=a_1v_1+a_2v_2+...+a_nv_n=\sum_i a_iv_i\)Span of Vectors\(v_i \in V_m\), \(w \in V_m\)Infinite-Ddimensional Vector Spac…

python的jieba

jieba 是一个广泛使用的 Python 中文分词库,主要用于将中文文本切分成独立的词语。 https://github.com/fxsjy/jieba 安装pip install jieba使用 (1)分词import jieba # 分词 text = "我爱自然语言处理" words = jieba.cut(text, cut_all=False) # 精确模式 prin…

3. 创建一个菜单组件-DeepSeek辅助编程

在deepseek中输入: 创建一个vue组件 组件实现菜单的功能 需要让调用该组件是可以自定义一些属性:mode:horizontal横向显示/vertical纵向显示,background-color,text-color,active-text-color,model:通过该model绑定菜单/model为MenuItem的数组 MenuItem由这些参数构成:inde…

微信支付相关配置

公众号相关配置 地址:https://mp.weixin.qq.com/一、获取用户openid相关配置 二、获取开发者ID(AppID)/开发者密码(AppSecret) 微信支付相关配置 地址:https://pay.weixin.qq.com/需要先申请开通支付产品微信支付相关参数获取: 一:获取商户号(商户号mach_id)三、获取证书…

华为开发者空间:基于DeepSeek+Cherry Studio构建模拟面试助手

通过实际操作,让开发者熟悉如何通过云主机部署DeepSeek,以及如何将DeepSeek与Cherry Studio结合起来帮助我们解决一些实际的问题。本文分享自华为云社区《华为开发者空间:基于DeepSeek+Cherry Studio构建模拟面试助手》,作者:开发者空间小蜜蜂。 1 案例介绍 CherryStudio …

​信创环境元宇宙应用:3种虚拟团队管理工具前瞻测评

随着信息技术的不断发展,信创环境下的元宇宙应用正逐渐成为各行业关注的焦点。在这个虚拟的世界中,虚拟团队的管理变得至关重要。本文将对三种虚拟团队管理工具进行前瞻测评,探讨它们在信创环境元宇宙应用中的优势和潜在挑战。 信创国产化项目管理解决方案 禅道是一款国产的…

VSCode+Linux+GCC编译运行数据结构的C语言程序集

背景 学习数据结构,写了很多C语言程序,这些C语言程序都保存在一个Git仓库中,以章节、实验内容为目录存放,形如:之前一直是通过gcc命令手动编译、运行,但随着程序逐渐复杂,希望简化构建过程,做到一键编译运行,同时支持断点调试。 环境VSCode,安装了C/C++扩展 Linux GC…

​信创项目管理认证解析:从SAFe到PMBOK的5大适配要点

在当今数字化时代,信创项目管理的重要性日益凸显。SAFe(Scaled Agile Framework,规模化敏捷框架)和 PMBOK(Project Management Body of Knowledge,项目管理知识体系)作为两种广泛应用的项目管理方法,如何实现它们之间的适配,以更好地推动信创项目的成功实施,是一个值…

mybatis如何使用注解方式,不使用xml

前言 大家好,我是小徐啊。我们在使用springboot开发的时候,一般是结合mybatis来使用的。而且,我们一般使用mybatis的时候,都是使用xml的文件。 不过,我之前在开发的时候,遇到了使用xml怎么也读取不到,可能是哪里配置的问题。这个时候,我就想到了使用注解的方式写sql,不…

SHP转WKT文件工具

SHP转WKT文件工具 *.shp转成wkt文件工具:将shp数据的图形转换成wkt工具 参数配置:param.yml设置shape路径,路径参数设置:shapeFile: “你的路径”;注:路径请使用"\\"或者’/’ ;避免使用含中文的路径示例: shapeFile: “C:/Users/Administrator/Desktop/wm/wm.s…