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

Head First Design Patterns - 装饰者模式

什么是装饰者模式

装饰者模式动态地将额外责任附加到对象上。对于拓展功能,装饰者提供子类化的弹性替代方案。 --《Head First Design Patterns》中的定义

为什么会有装饰者模式

根据上述定义,简单来说,装饰者模式就是对原有的类,增加一些额外的功能或者行为。用普通的继承或者组合也可以实现,但是单纯用继承或者组合来做,会产生大量的拓展类而导致"类爆炸"。

书中用咖啡的价格为例,说明了类爆炸这个概念:

咖啡店的咖啡的种类有4种,每种的价格不一样
在这里插入图片描述

若除了咖啡本身,还可以要求加上不同的调料,例如蒸奶(milk)、豆奶(soy)、摩卡(Mocha)。这样子,子类的拓展组合,就会有很多种,从而导致类爆炸,如下图所示。
在这里插入图片描述

装饰者模式的特点

  • 装饰者和被装饰者继承同一个基类。因为装饰者必须能够取代被装饰者,这里利用继承达到“类型匹配”,而不是利用继承获取“行为”
  • 装饰者拥有(has a)一个与被装饰者相同的基类类型属性(类似策略模式)
  • 可以用一个或多个装饰者类包装同一个对象
  • 装饰者可以在所委托被装饰者的行为之前或行为之后或行为之前与之后加上自己的行为,以达到特定的目的

装饰者模式的类图

在这里插入图片描述

例子

以上述咖啡店的咖啡价格为例子

  1. 基类:对应上图中的Component
public abstract class Beverage {String description = "Unknown Beverage";public String getDescription() {return description;}public abstract double cost();
}

2. 咖啡种类的拓展类: 对应上图中的ConcreteComponent

public class Espresso extends Beverage{public Espresso() {description = "Espresso";}@Overridepublic double cost() {return 1.99;}
}public class HouseBlend extends Beverage {public HouseBlend() {description = "HouseBlend";}@Overridepublic double cost() {return .89;}
}

3. 调料类

public class Mocha extends CondimentDecorator {public Mocha(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ", Mocha";}@Overridepublic double cost() {return beverage.cost() + .20;}
}public class Whip extends CondimentDecorator{public Whip(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ", whip";}@Overridepublic double cost() {return beverage.cost() + .10;}
}

4. 测试

public static void main(String[] args) {// 要一杯浓缩咖啡,不加调料Beverage beverage = new Espresso();System.out.println(beverage.getDescription() + " $" + beverage.cost());//要一杯HouseLand,带有2份mocha和whipBeverage beverage1 = new HouseBlend();beverage1 = new Mocha(beverage1);beverage1 = new Mocha(beverage1);beverage1 = new Whip(beverage1);System.out.println(beverage1.getDescription() + " $" + beverage1.cost());}

上述的咖啡喝调料可以在不改动基类代码的基础上,进行随意组合。

装饰者模式用到的设计原则

类应该对拓展开放,对修改关闭(开闭原则)

应用

java中的I/O流
在这里插入图片描述
参考:装饰者模式

相关文章:

Head First Design Patterns - 装饰者模式

什么是装饰者模式 装饰者模式动态地将额外责任附加到对象上。对于拓展功能,装饰者提供子类化的弹性替代方案。 --《Head First Design Patterns》中的定义 为什么会有装饰者模式 根据上述定义,简单来说,装饰者模式就是对原有的类&#xff0c…...

MySQL 执行过程

MySQL 的执行流程也确实是一个复杂的过程,它涉及多个组件的协同工作,故而在面试或者工作的过程中很容易陷入迷惑和误区。 MySQL 执行过程 本篇将以 MySQL 常见的 InnoDB 存储引擎为例,为大家详细介绍 SQL 语句的执行流程。从连接器开始&…...

判断电话号码是否重复-excel

有时候重复的数据不需要或者很烦人,就需要采取措施,希望以下的方法能帮到你。 1.判断是否重复 方法一: 1)针对第一个单元格输入等号,以及公式countif(查找记录数的范围,需要查找的单元格) 2…...

【Java开发岗面试】八股文—Java虚拟机(JVM)

声明: 背景:本人为24届双非硕校招生,已经完整经历了一次秋招,拿到了三个offer。本专题旨在分享自己的一些Java开发岗面试经验(主要是校招),包括我自己总结的八股文、算法、项目介绍、HR面和面试…...

【Linux】Linux 下基本指令 -- 详解

无论是什么命令,用于什么用途,在 Linux 中,命令有其通用的格式: command [-options] [parameter] command:命令本身。-options:[可选,非必填]命令的一些选项,可以通过选项控制命令的…...

Eureka注册及使用

一、Eureka的作用 Eureka是一个服务注册与发现的工具,主要用于微服务架构中的服务发现和负载均衡。其主要作用包括: 服务提供者将自己注册到Eureka Server上,包括服务的地址和端口等信息。服务消费者从Eureka Server上获取服务提供者的地址…...

Ubuntu之修改时区/时间

1、查看当前时间及时区状态 sudo timedatectl status # 显示当前时区为Asia/Shanghai 2、查看当前系统时间 sudo date 3、查看当前系统时间及时区 sudo date -R # 显示当前时间及对应时区,时区为“0800”北京时区 4、修改硬件时间 修改日期格式&#xff1a…...

4、内存泄漏检测(多线程)

4、内存泄漏多线程 多线程下使用Valgrind 工具的memcheck检查. 安装 sudo apt install valgrind使用 valgrind --toolmemcheck --leak-checkfull ./app_main 指令效果如下所示. wqwq-Virtual-Machine:~/work/test_zlog/build$ valgrind --toolmemcheck --leak-checkfull .…...

在使用tcp长连接时,是否还需要再引入重发机制?

一 什么是tcp长连接? 在TCP(Transmission Control Protocol)中,长连接是指在通信过程中保持连接状态的一种方式,相对于短连接而言。长连接通常用于需要频繁通信的场景,以减少连接建立和断开的开销。在长连接…...

记一次Oracle Cloud计算实例ssh恢复过程

#ssh秘钥丢失# , #Oracle Cloud# 。 电脑上的ssh秘钥文件不知道什么时候丢失了,直到用的时候才发现没有了,这下可好,Oracle Cloud的计算实例连不上了,这个实例只能通过ssh连接上去: 以下是解决步骤&#x…...

2024年01月数据库流行度最新排名

点击查看最新数据库流行度最新排名(每月更新) 2024年01月数据库流行度最新排名 TOP DB顶级数据库索引是通过分析在谷歌上搜索数据库名称的频率来创建的 一个数据库被搜索的次数越多,这个数据库就被认为越受欢迎。这是一个领先指标。原始数…...

Stable Diffusion API入门:简明教程

Stable Diffusion 是一个先进的深度学习模型,用于创造和修改图像。这个模型能够基于文本描述来生成图像,让机器理解和实现用户的创意。使用这项技术的关键在于掌握其 API,通过编程来操控图像生成的过程。 在探索 Stable Diffusion API 的世界…...

数据结构--二叉搜索树的实现

目录 1.二叉搜索树的概念 2.二叉搜索树的操作 二叉搜索树的插入 中序遍历(常用于排序) 二叉搜索树的查找 二叉搜索树的删除 完整二叉树代码: 二叉搜索树的应用 key/value搜索模型整体代码 1.二叉搜索树的概念 二叉搜索树又称二叉排序树,它或者是一…...

《微信小程序开发从入门到实战》学习六十八

6.6 网络API 6.6.1 网络API 使用wx.request接口可以发起网络请求。该接口接受一个Object参,参数支持属性如下所示: url(必填):开发者服务器地址 data:请求的参数,类型为string/object/ArrayBuffer header&#xf…...

阿里是如何去“O”的?

大家好,我是老猫,猫头鹰的“猫”。 今天我们来聊聊数据库这个话题。 2009年,阿里提出“去IOE化”的概念,这在当时看起来是天方夜谭,但目前来看可以说是"轻舟已过万重山"。 IOE是传统IT三大件,…...

蓝桥杯备赛 day 1 —— 递归 、递归、枚举算法(C/C++,零基础,配图)

目录 🌈前言 📁 枚举的概念 📁递归的概念 例题: 1. 递归实现指数型枚举 2. 递归实现排列型枚举 3. 递归实现组合型枚举 📁 递推的概念 例题: 斐波那契数列 📁习题 1. 带分数 2. 反硬币 3. 费解的…...

87 双指针解验证回文字符串II

问题描述:简单给定一个非空字符串s,最多删除一个字符,判断是否成为回文字符串。 双指针解法:指针1指向开头,指针2指向结尾,定义一个count记录不满足回文串的数量,若超过1,则返回fal…...

【排序算法】【二叉树】【滑动窗口】LeetCode220: 存在重复元素 III

作者推荐 【二叉树】【单调双向队列】LeetCode239:滑动窗口最大值 本文涉及的基础知识点 C算法&#xff1a;滑动窗口总结 题目 给你一个整数数组 nums 和两个整数 indexDiff 和 valueDiff 。 找出满足下述条件的下标对 (i, j)&#xff1a; i ! j, abs(i - j) < indexDi…...

OS 7--DNS配置+Apache发布网站

环境准备 centOS 7 1.配置DNS 1.1 域名为lianxi.com 1.2 为WWW服务器、FTP服务器、NEWS服务器做域名解析 1)安装DNS yum -y install bind bind-utils (如果安装不上&#xff0c;就把磁盘在重洗挂载一下&#xff09; 2&#xff09;修改DNS配置文件 vim /etc/resolv.conf…...

1月2日代码随想录二叉树的最小深度及层序遍历总结

个人认为这么一个层序遍历的章节放这么多基本一样的题目算是很没意思的了 填充每个节点的下一个右侧节点和二叉树最大深度和前面的代码几乎完全一样&#xff0c;所以我就跳过了 代码随想录 (programmercarl.com) 代码随想录 (programmercarl.com) 111.二叉树的最小深度 给…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

初级程序员入门指南

初级程序员入门指南 在数字化浪潮中&#xff0c;编程已然成为极具价值的技能。对于渴望踏入程序员行列的新手而言&#xff0c;明晰入门路径与必备知识是开启征程的关键。本文将为初级程序员提供全面的入门指引。 一、明确学习方向 &#xff08;一&#xff09;编程语言抉择 编…...

ubuntu清理垃圾

windows和ubuntu 双系统&#xff0c;ubuntu 150GB&#xff0c;开发用&#xff0c;基本不装太多软件。但是磁盘基本用完。 1、查看home目录 sudo du -h -d 1 $HOME | grep -v K 上面的命令查看$HOME一级目录大小&#xff0c;发现 .cache 有26GB&#xff0c;.local 有几个GB&am…...

在Android13上添加系统服务的好用例子

在Android13上添加一个自动的system service例子 留好&#xff0c;备用。 --- .../prebuilts/api/30.0/plat_pub_versioned.cil | 76 - .../prebuilts/api/31.0/plat_pub_versioned.cil | 94 - .../prebuilts/api/32.0/plat_pub_versioned.cil | 94 - frameworks/base/co…...

我认为STM32输入只分为模拟输入 与 数字输入

核心概念解析 模拟输入 (Analog Input) 设计目的&#xff1a;直接连接模拟信号&#xff08;如ADC采集电压、温度传感器输出&#xff09; 硬件行为&#xff1a; ✅ 断开内部数字电路&#xff08;施密特触发器禁用&#xff09; ✅ 信号直通模拟外设&#xff08;如ADC、运放&…...