当前位置: 首页 > news >正文

23种设计模式之【装饰器模式】-核心原理与 Java实践

23种设计模式之【装饰器模式】-核心原理与 Java实践

  • 装饰器模式(Decorator Pattern)
  • 核心原理
  • Java 实践示例
  • 装饰器模式的特点
  • 装饰器模式的应用场景

装饰器模式(Decorator Pattern)

装饰器模式是 23 种设计模式中的一种结构型模式,其核心思想是动态地给一个对象添加额外的职责,就像在墙上刷油漆一样,不改变原有对象的结构,但能增强其功能。这种模式相比继承更灵活,可以在运行时动态扩展对象功能,且支持多层嵌套装饰。

核心原理

抽象组件(Component)
定义被装饰对象和装饰器的共同接口
是所有具体组件和装饰器的超类型
具体组件(ConcreteComponent)
实现抽象组件接口,是被装饰的原始对象
包含核心业务逻辑
抽象装饰器(Decorator)
实现抽象组件接口,持有一个抽象组件的引用
定义所有具体装饰器的公共行为
具体装饰器(ConcreteDecorator)
继承抽象装饰器,实现具体的增强功能
在调用被装饰对象的方法前后添加额外操作

装饰器模式的核心是 “组合替代继承”,通过嵌套组合多个装饰器,实现对对象功能的灵活扩展。

Java 实践示例

以 “咖啡订单系统” 为例实现装饰器模式:
基础咖啡(如美式咖啡)是被装饰的原始对象
可以添加各种配料(牛奶、糖、巧克力)作为装饰器,动态增强咖啡的功能

package com.example.demo;public class DecoratorPattern {public static void main(String[] args) {// 点一杯基础美式咖啡Coffee coffee = new Americano();System.out.println(coffee.getDescription() + ",价格:" + coffee.cost() + "元");// 加牛奶coffee = new MilkDecorator(coffee);System.out.println(coffee.getDescription() + ",价格:" + coffee.cost() + "元");// 再加糖coffee = new SugarDecorator(coffee);System.out.println(coffee.getDescription() + ",价格:" + coffee.cost() + "元");// 点一杯拿铁,加巧克力Coffee latte = new Latte();latte = new ChocolateDecorator(latte);System.out.println(latte.getDescription() + ",价格:" + latte.cost() + "元");}// 抽象组件:咖啡接口public interface Coffee {// 获取咖啡描述String getDescription();// 计算价格double cost();}// 具体组件:美式咖啡public static class Americano implements Coffee {@Overridepublic String getDescription() {return "美式咖啡";}@Overridepublic double cost() {return 25.0;}}// 具体组件:拿铁咖啡public static class Latte implements Coffee {@Overridepublic String getDescription() {return "拿铁咖啡";}@Overridepublic double cost() {return 32.0;}}// 抽象装饰器:咖啡装饰器public abstract static class CoffeeDecorator implements Coffee {protected Coffee coffee; // 持有被装饰的咖啡对象// 通过构造函数注入被装饰对象public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic String getDescription() {return coffee.getDescription();}@Overridepublic double cost() {return coffee.cost();}}// 具体装饰器:牛奶public static class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return coffee.getDescription() + " + 牛奶";}@Overridepublic double cost() {return coffee.cost() + 5.0; // 加牛奶增加5元}}// 具体装饰器:糖public static class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return coffee.getDescription() + " + 糖";}@Overridepublic double cost() {return coffee.cost() + 2.0; // 加糖增加2元}}// 具体装饰器:巧克力public static class ChocolateDecorator extends CoffeeDecorator {public ChocolateDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return coffee.getDescription() + " + 巧克力";}@Overridepublic double cost() {return coffee.cost() + 8.0; // 加巧克力增加8元}}
}

美式咖啡,价格:25.0元
美式咖啡 + 牛奶,价格:30.0元
美式咖啡 + 牛奶 + 糖,价格:32.0元
拿铁咖啡 + 巧克力,价格:40.0元

装饰器模式的特点

优点:
灵活性高:可以动态地给对象添加或移除功能,比继承更灵活
组合性强:支持多层装饰,通过不同组合实现多样化功能
遵循开闭原则:新增装饰器无需修改原有代码
单一职责:每个装饰器只负责一种增强功能,职责清晰
缺点:
复杂度增加:多层装饰可能导致系统中出现大量小对象
调试困难:调用链较长时,排查问题需要逐层分析
与继承的区别:
继承:编译期静态扩展,功能固定,不灵活
装饰器:运行时动态扩展,可灵活组合,功能可变

装饰器模式的应用场景

IO 流(Java 经典应用):
InputStream/OutputStream、Reader/Writer体系中大量使用装饰器
例如:BufferedInputStream装饰FileInputStream增加缓冲功能,DataInputStream增加数据类型处理功能

// Java IO中的装饰器模式
InputStream is = new FileInputStream("data.txt");
InputStream bis = new BufferedInputStream(is); // 增加缓冲功能
DataInputStream dis = new DataInputStream(bis); // 增加数据类型处理功能

GUI 组件:
图形界面中给组件添加边框、滚动条等装饰
例如:JScrollPane装饰JTextArea添加滚动功能
日志增强:
给方法调用添加日志记录、性能监控等功能
例如:在原有业务方法前后添加日志打印装饰器
权限控制:
动态为不同用户添加不同的操作权限
例如:普通用户→VIP 用户→管理员的权限装饰链

装饰器模式是扩展对象功能的重要方式,尤其适合需要灵活组合多种功能的场景。Java IO 流是装饰器模式的典范,通过嵌套不同的装饰器,实现了丰富的 IO 操作功能

http://www.dtcms.com/a/393615.html

相关文章:

  • 动态规划中的背包问题:0/1 背包与完全背包的核心解析
  • PHP应用-组件框架前端模版渲染三方插件富文本编辑器CVE审计(2024小迪安全DAY30笔记)
  • uniapp 如何判断发的请求是网络异常uni.request
  • 学习:uniapp全栈微信小程序vue3后台 (25)
  • 23种设计模式之【原型模式】-核心原理与 Java实践
  • Netty 重放解码器ReplayingDecoder揭秘:重写轻量异常机制 和 ConstantPool
  • getgeo 生物信息 R语言 表型信息表”“样本信息表”或“临床信息表 phenodata phenotype data
  • OceanBase备租户创建(二):通过BACKUP DATABASE PLUS ARCHIVELOG
  • Linux文件打包压缩与软件安装管理完全指南
  • KingbaseES数据备份操作详解(图文教程)
  • 中断屏蔽实现方法-ARM内核
  • Kotlin 协程之 SharedFlow 与 StateFlow 深度解析
  • python爬虫(请求+解析+案例)
  • 111-Christopher-Dall_Arm-Timers-and-Fire:Arm架构计时器与半虚拟化时间
  • switch缺少break出现bug
  • 【自然语言处理】(3) --RNN循环神经网络
  • C# 中的 ReferenceEquals 方法
  • BERT:用于语言理解的深度双向Transformer预训练【简单分析】
  • 力扣hot100:两数相加(模拟竖式加法详解)(2)
  • Zotero + Word 插件管理参考文献的引用
  • 用Python一键整理文件:自动分类DOCX与PDF,告别文件夹杂乱
  • Ubuntu部署Elasticsearch教程
  • 61.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--新增功能--提取金额
  • 一款基于 .NET 开源、免费、命令行式的哔哩哔哩视频内容下载工具
  • Win Semi宣布推出线性优化的GaN工艺
  • 考研408计算机网络2025年第38题真题解析
  • C++编写的经典贪吃蛇游戏
  • 风险预测模型原理
  • PS练习5:利用翻转制作图像倒影
  • 平替Jenkins,推荐一款国产开源免费的CICD工具 - Arbess