(八)趣学设计模式 之 装饰器模式!

在这里插入图片描述

目录

    • 一、 啥是装饰器模式?
    • 二、 为什么要用装饰器模式?
    • 三、 装饰器模式的实现方式
    • 四、 装饰器模式的优缺点
    • 五、 装饰器模式的应用场景
    • 六、 装饰器模式 vs 代理模式
    • 七、 总结

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解适配器模式请看: (七)趣学设计模式 之 适配器模式!

这篇文章带你详细认识一下设计模式中的装饰器模式

一、 啥是装饰器模式?

想象一下,你点了一杯咖啡 ☕️,觉得味道有点单调,想加点料,比如加一份牛奶 🥛,或者加一份糖 🍬,甚至加一份巧克力酱 🍫。 每次加料,咖啡的味道都会变得不一样 😋。

装饰器模式,就是用来动态地给一个对象添加一些额外的职责! 它可以让你在不修改原有对象的基础上,扩展对象的功能 ➕。

简单来说,就是给对象穿上不同的“衣服”,让它拥有不同的功能! 🧥👔

  • 你想给一个对象添加一些额外的功能,但是不想修改它的代码: 就像你想给咖啡加料,但是不想修改咖啡的制作方法 ☕️!
  • 你想动态地给对象添加功能,而不是静态地继承: 就像你想根据自己的喜好,随时给咖啡加不同的料 🥛🍬🍫!
  • 你想避免创建大量的子类: 就像你不想为每种加料的咖啡都创建一个新的类 ☕️+🥛, ☕️+🍬, ☕️+🍫!

二、 为什么要用装饰器模式?

用装饰器模式,好处多多 👍:

  • 扩展性好: 可以动态地添加新的装饰器,扩展对象的功能 ➕!
  • 灵活性高: 可以灵活地组合不同的装饰器,实现不同的功能组合 🤸!
  • 符合开闭原则: 可以在不修改原有代码的情况下,增加新的装饰器,扩展功能 🆕!
  • 避免了继承带来的类爆炸问题: 不需要创建大量的子类,减少了类的数量 💥!

三、 装饰器模式的实现方式

装饰器模式主要包含以下几个角色:

  • Component(组件): 定义一个对象接口,可以给这些对象动态地添加职责。 ☕️ (比如:咖啡)
  • ConcreteComponent(具体组件): 定义一个具体的对象,实现了组件接口。 ☕️ (比如:原味咖啡)
  • Decorator(装饰器): 包含一个指向组件对象的引用,并定义一个与组件接口一致的接口。 🧥 (比如:调味品)
  • ConcreteDecorator(具体装饰器): 具体的装饰器类,负责给组件对象添加额外的职责。 🥛🍬🍫 (比如:牛奶、糖、巧克力酱)

代码示例:

// 组件接口:咖啡
public interface Coffee {
    String getDescription(); // 获取描述
    double getCost(); // 获取价格
}

// 具体组件:原味咖啡
public class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "原味咖啡";
    }

    @Override
    public double getCost() {
        return 10.0;
    }
}

// 装饰器:调味品
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee; // 组合咖啡对象

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public String getDescription() {
        return coffee.getDescription();
    }

    @Override
    public double getCost() {
        return coffee.getCost();
    }
}

// 具体装饰器:牛奶
public class Milk extends CoffeeDecorator {
    public Milk(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", 加牛奶";
    }

    @Override
    public double getCost() {
        return super.getCost() + 2.0;
    }
}

// 具体装饰器:糖
public class Sugar extends CoffeeDecorator {
    public Sugar(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", 加糖";
    }

    @Override
    public double getCost() {
        return super.getCost() + 1.0;
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee(); // 创建原味咖啡
        System.out.println(coffee.getDescription() + ", 价格:" + coffee.getCost());

        coffee = new Milk(coffee); // 加牛奶
        System.out.println(coffee.getDescription() + ", 价格:" + coffee.getCost());

        coffee = new Sugar(coffee); // 加糖
        System.out.println(coffee.getDescription() + ", 价格:" + coffee.getCost());
    }
}

分析:

  • Coffee 是组件接口,定义了咖啡的描述和价格。
  • SimpleCoffee 是具体组件,实现了原味咖啡。
  • CoffeeDecorator 是装饰器,组合了咖啡对象,并实现了咖啡接口。
  • MilkSugar 是具体装饰器,分别给咖啡添加了牛奶和糖。

输出结果:

原味咖啡, 价格:10.0
原味咖啡, 加牛奶, 价格:12.0
原味咖啡, 加牛奶, 加糖, 价格:13.0

四、 装饰器模式的优缺点

优点:

  • 扩展性好 ➕!
  • 灵活性高 🤸!
  • 符合开闭原则 🆕!
  • 避免了继承带来的类爆炸问题 💥!

缺点:

  • 增加了系统的复杂度 😫!
  • 可能会产生很多小对象 👶!
  • 调试困难,特别是当有很多装饰器的时候 🐛!

五、 装饰器模式的应用场景

  • 动态地给对象添加职责: 就像给咖啡加料,或者给汽车加装配件 🚗!
  • 需要灵活地组合不同的功能: 就像给文本编辑器添加不同的功能,比如加粗、斜体、下划线 📝!
  • 避免创建大量的子类: 就像避免为每种加料的咖啡都创建一个新的类 ☕️+🥛, ☕️+🍬, ☕️+🍫!
  • IO流: Java IO流中大量使用了装饰器模式,例如 BufferedInputStreamBufferedOutputStream 都是装饰器,用于提高IO效率。

六、 装饰器模式 vs 代理模式

代理模式请看:(六)趣学设计模式 之 代理模式!

特性装饰器模式代理模式
目的动态地给对象添加额外的职责 ➕控制对对象的访问 👮
关注点扩展功能控制访问
关系装饰器和组件之间是“is-a”关系(接口)代理和真实对象之间是“is-a”关系(接口)
组合装饰器组合的是组件对象,可以多层组合 ☕️+🥛+🍬代理组合的是真实对象,通常只有一层 🧑‍💼+🏠
透明性客户端通常知道它正在使用装饰器 👁️客户端通常不知道它正在使用代理 🙈
例子咖啡加料 ☕️+🥛+🍬房产中介 🧑‍💼+🏠
常见应用IO流,GUI组件远程代理,虚拟代理,保护代理,缓存代理
核心区别扩展对象的功能,不改变原有接口控制对对象的访问,可以改变原有接口的行为

七、 总结

  • 装饰器模式就像给对象穿衣服,让它拥有不同的功能! 🧥
  • 主要包含组件、具体组件、装饰器和具体装饰器四个角色! 🎭
  • 优点是扩展性好、灵活性高、符合开闭原则、避免类爆炸! 👍
  • 缺点是增加复杂度、可能产生很多小对象、调试困难! 👎
  • 适用于需要动态地给对象添加职责,并且需要灵活地组合不同的功能的场景! 🎯

希望这篇文章能让你彻底理解装饰器模式! 💯 祝你学习愉快! 😄
看完请看:(九)趣学设计模式 之 桥接模式!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快节奏生活

在当今快节奏的商务环境中,效率成为了决定企业竞争力的关键因素之一。亿可达软件连接平台,以其独特的功能和优势,为职场人士带来了前所未有的便捷与高效,成为了众多用户心中的“宝藏”工具。 1、亿可达:自动化流程的搭…

Jenkins protoc: command not found

个人博客地址:Jenkins protoc: command not found | 一张假钞的真实世界 在使用Jenkins编译Hadoop3.1.2时报错信息如下: [INFO] --- hadoop-maven-plugins:3.1.2:protoc (compile-protoc) hadoop-common --- [WARNING] [protoc, --version] failed: j…

SOME/IP协议的建链过程

在SOME/IP协议中,建立服务通信链路的过程主要涉及服务发现机制,通常需要以下三次交互: 服务提供者广播服务可用性(Offer Service) 服务提供者启动后,周期性地通过Offer Service消息向网络广播其提供的服务实例信息(如Service ID、Instance ID、通信协议和端口等)。 作用…

考研/保研复试英语问答题库(华工建院)

华南理工大学建筑学院保研/考研 英语复试题库,由华工保研er和学硕笔试第一同学一起整理,覆盖面广,助力考研/保研上岸!需要👇载可到文章末尾见小🍠。 以下是主要内容: Part0 复试英语的方法论 Pa…

Linux7-线程

一、前情回顾 chdir();功能: 函数用于改变当前进程的工作目录。 参数:路径(Path):这是一个字符串参数,表示要切换到的目标目录的路径。 返回值: 成功:在成功改变当前工作目…

防火墙双机热备---VRRP,VGMP,HRP(超详细)

双机热备技术-----VRRP,VGMP,HRP三个组成 注:与路由器VRRP有所不同,路由器是通过控制开销值控制数据包流通方向 防火墙双机热备: 1.主备备份模式 双机热备最大的特点就是防火墙提供了一条专门的备份通道(心…

LabVIEW形状误差测量系统

在机械制造领域,形状与位置公差(GD&T)直接影响装配精度与产品寿命。国内中小型机加工企业因形状误差导致的返工率高达12%-18%。传统测量方式存在以下三大痛点: ​ 设备局限:机械式千分表需人工读数,精度…

本地部署大模型: LM Studio、Open WebUI 与 Chatbox 全面对比以及选型指南

1. 工具概述 LM Studio 定位:专注于本地化大模型实验与推理的桌面工具,支持多模型并行、Hugging Face集成及离线运行。 核心功能: 图形化界面直接加载GGUF模型文件,支持NVIDIA/AMD GPU加速。 内置OpenAI兼容API,可搭…

百度觉醒,李彦宏渴望光荣

文 | 大力财经 作者 | 魏力 2025年刚刚开年,被一家名为DeepSeek的初创公司强势改写。在量化交易出身的创始人梁文锋的带领下,这支团队以不到ChatGPT 6%的训练成本,成功推出了性能可与OpenAI媲美的开源大模型。 此成果一经问世,…

mysql 迁移到人大金仓数据库

我是在windows上安装了客户端工具 运行数据库迁移工具 打开 在浏览器输入http://localhost:54523/ 账号密码都是kingbase 添加mysql源数据库连接 添加人大金仓目标数据库 添加好的两个数据库连接 新建迁移任务 选择数据库 全选 迁移中 如果整体迁移不过去可以单个单个或者几个…

Spring Cloud — Hystrix 服务隔离、请求缓存及合并

Hystrix 的核心是提供服务容错保护,防止任何单一依赖耗尽整个容器的全部用户线程。使用舱壁隔离模式,对资源或失败单元进行隔离,避免一个服务的失效导致整个系统垮掉(雪崩效应)。 1 Hystrix监控 Hystrix 提供了对服务…

【链 表】

【链表】 一级目录1. 基本概念2. 算法分析2.1 时间复杂度2.2 空间复杂度2.3 时空复杂度互换 线性表的概念线性表的举例顺序表的基本概念顺序表的基本操作1. 初始化2. 插入操作3. 删除操作4. 查找操作5. 遍历操作 顺序表的优缺点总结优点缺点 树形结构图形结构单链表基本概念链表…

记录锁,间隙锁,Next-Key Lock

记录锁,间隙锁,Next-Key Lock mysql的锁机制一、InnoDB行锁的种类1、记录锁(Record Lock)(1)不加索引,两个事务修改同一行记录(2)不加索引,两个事务修改同一表…

vue3父子组件props传值,defineprops怎么用?(组合式)

目录 1.基础用法 2.使用解构赋值的方式定义props 3.使用toRefs的方式解构props (1).通过ref响应式变量&#xff0c;修改对象本身不会触发响应式 1.基础用法 父组件通过在子组件上绑定子组件中定义的props&#xff08;:props“”&#xff09;传递数据给子组件 <!-- 父组件…

鸿蒙Next-方法装饰器以及防抖方法注解实现

以下是关于 鸿蒙Next&#xff08;HarmonyOS NEXT&#xff09;中 MethodDecorator 的详细介绍及使用指南&#xff0c;结合了多个技术来源的实践总结&#xff1a; 一、MethodDecorator 的概念与作用 MethodDecorator 是鸿蒙Next框架中用于装饰类方法的装饰器&#xff0c;属于 Ark…

快速入门——状态管理VueX

Vuex介绍 状态管理 每一个Vuex应用的核心都是一个store&#xff0c;与普通的全局对象不同的是&#xff0c;基于Vue数据与视图绑定的特点&#xff0c;当store中的状态发生变化时&#xff0c;与之绑定的视图也会被重新渲染。 store中的状态不允许被直接修改&#xff0c;改变sto…

java进阶学习脑图

今天开始分享我的第一篇博客&#xff0c;先放上我自己花费一个月完成的java进阶学习脑图吧&#xff01; 谁都想像R大一样对JVM可以知无不言&#xff0c;言无不尽&#xff1b; 谁都想像Doug Lea一样可以参与JUC这种核心模块的开发&#xff1b; 但是&#xff0c;不能只停留在想…

【设计师专属】智能屏幕取色器Pro|RGB/HEX双模式|快捷键秒存|支持导出文档|C++ QT

&#x1f525; “1秒锁定千万色值&#xff0c;让灵感不再流失&#xff01;” ✔ 像素级精准捕捉 ✔ 快捷键极速记录 ✔ 数据一键导出 ✔ 开发者/设计师效率神器 "还在手动截图比色&#xff1f;加班改稿只因色差&#xff1f;前端还原总被吐槽&#xff1f; &#x1f449;…

力扣 下一个排列

交换位置&#xff0c;双指针&#xff0c;排序。 题目 下一个排列即在组成的排列中的下一个大的数&#xff0c;然后当这个排列为降序时即这个排列最大&#xff0c;因为大的数在前面&#xff0c;降序排列的下一个数即升序。所以&#xff0c;要是想找到当前排列的下一个排列&…

在 HuggingFace 中使用 SSH 进行下载数据集和模型

SSH 是一种 安全通讯的协议&#xff0c;我们通过配置 SSH 的密钥 来在 Git 上实现 Huggingface 模型的命令行下载。 参考网址&#xff1a;https://huggingface.co/docs/hub/security-git-ssh 点击自己的头像&#xff0c;点击 Add SSH key 在 Windows 上&#xff0c;我们实现已…