装饰者模式(设计模式)
装饰模式就是对一个类进行装饰,增强其方法行为,在装饰模式中,作为原来的这个类使用者还不应该感受到装饰前与装饰后有什么不同,否则就破坏了原有类的结构了,所以装饰器模式要做到对被装饰类的使用者透明,这是对装饰器模式的一个要求。总之装饰器设计模式就是对于原有功能的扩展
不改变原有代码基础之上 额外实现增强。装饰者模式是一种结构型设计模式,它允许你在运行时为对象动态添加新的行为,同时不改变其原有的结构。这种模式是作为替代继承的一种方式而存在的。
在装饰者模式中,有一个抽象组件(Component)定义了基本功能,并且可以有一个或多个具体组件(ConcreteComponent)实现这些基本功能。此外,还有一个抽象装饰者(Decorator)类,它也实现了抽象组件,并且包含了一个指向抽象组件的引用。具体装饰者(ConcreteDecorator)类继承自抽象装饰者类,并且可以在运行时为抽象组件添加新的行为。
装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地给对象添加职责(功能)。装饰者模式与继承不同,它通过创建装饰者类来包装原始类,而不是通过继承来扩展功能。装饰者模式在许多情况下非常有用,特别是在需要组合功能或动态地调整功能的时候。
优点
- 灵活性:通过组合不同的装饰器,可以灵活地为对象添加不同的功能。
- 遵循开闭原则:不修改现有类的情况下扩展功能。
- 细粒度控制:可以对对象功能进行细粒度控制和组合。
缺点 - 复杂性:会增加系统的复杂性,尤其是在有大量不同装饰器的时候。
- 性能:可能会增加系统的性能开销,特别是在装饰器链比较长的情况下。
装饰者模式非常适合那些需要在不修改类定义的情况下动态地添加功能的场景。
装饰者模式的组成
装饰者模式主要包括以下几个部分:
组件接口(Component):定义对象的接口,可以是具体组件或装饰器共同实现的接口。
具体组件(ConcreteComponent):实现组件接口的基本功能对象。
装饰器抽象类(Decorator):实现组件接口,并包含一个组件接口的引用,可以是具体组件或另一个装饰器。
具体装饰器(ConcreteDecorator):继承装饰器抽象类,添加额外的功能。
UML 类图
Component (接口)
^
|
ConcreteComponent (具体组件)
^
|
Decorator (装饰器抽象类)
^
|
ConcreteDecoratorA, ConcreteDecoratorB (具体装饰器)
装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地给对象添加职责(功能)。装饰者模式与继承不同,它通过创建装饰者类来包装原始类,而不是通过继承来扩展功能。装饰者模式在许多情况下非常有用,特别是在需要组合功能或动态地调整功能的时候。
UML 类图
Component (接口)
^
|
ConcreteComponent (具体组件)
^
|
Decorator (装饰器抽象类)
^
|
ConcreteDecoratorA, ConcreteDecoratorB (具体装饰器)
java样例1
以下是一个简单的 Java 示例,展示了如何使用装饰者模式:
// 组件接口
public interface Coffee {String getDescription();double getCost();
}// 具体组件
public class SimpleCoffee implements Coffee {@Overridepublic String getDescription() {return "Simple coffee";}@Overridepublic double getCost() {return 2.0;}
}// 装饰器抽象类
public abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}@Overridepublic double getCost() {return decoratedCoffee.getCost();}
}// 具体装饰器A
public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return decoratedCoffee.getDescription() + ", Milk";}@Overridepublic double getCost() {return decoratedCoffee.getCost() + 0.5;}
}// 具体装饰器B
public class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return decoratedCoffee.getDescription() + ", Sugar";}@Overridepublic double getCost() {return decoratedCoffee.getCost() + 0.2;}
}// 使用装饰者模式
public class DecoratorPatternDemo {public static void main(String[] args) {Coffee coffee = new SimpleCoffee();System.out.println(coffee.getDescription() + " $" + coffee.getCost());coffee = new MilkDecorator(coffee);System.out.println(coffee.getDescription() + " $" + coffee.getCost());coffee = new SugarDecorator(coffee);System.out.println(coffee.getDescription() + " $" + coffee.getCost());}
}
运行结果
Simple coffee $2.0
Simple coffee, Milk $2.5
Simple coffee, Milk, Sugar $2.7
解释
- 组件接口(Coffee):定义了 getDescription 和 getCost 方法。
- 具体组件(SimpleCoffee):实现了组件接口,表示基本的咖啡。
- 装饰器抽象类(CoffeeDecorator):实现了组件接口,并持有一个组件接口的引用。
- 具体装饰器(MilkDecorator 和 SugarDecorator):扩展了装饰器抽象类,为咖啡添加额外的功能(牛奶和糖)。
Java样例2
下面是一个简单的装饰者模式的示例,假设我们有一个接口 Shape 表示图形,以及一个具体实现 Circle:
public interface Shape {void draw();
}public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing Circle");}
}
然后我们创建一个抽象装饰者 ShapeDecorator,它也实现了 Shape 接口,并且包含了一个指向 Shape 的引用:
public abstract class ShapeDecorator implements Shape {protected Shape decoratedShape;public ShapeDecorator(Shape decoratedShape) {this.decoratedShape = decoratedShape;}public void draw() {decoratedShape.draw();}
}
接着,我们可以创建具体的装饰者,例如 RedShapeDecorator,它继承自 ShapeDecorator 并且在原有的基础上添加新的行为:
public class RedShapeDecorator extends ShapeDecorator {public RedShapeDecorator(Shape decoratedShape) {super(decoratedShape);}@Overridepublic void draw() {decoratedShape.draw();setRedBorder(decoratedShape);}private void setRedBorder(Shape decoratedShape){System.out.println("Border Color: Red");}
}
最后,我们可以使用装饰者模式来动态地为对象添加新的行为,例如:
public class DecoratorPatternDemo {public static void main(String[] args) {Shape circle = new Circle();Shape redCircle = new RedShapeDecorator(new Circle());System.out.println("Circle with normal border");circle.draw();System.out.println("\nCircle of red border");redCircle.draw();}
}
在这个示例中,RedShapeDecorator 动态地为 Circle 对象添加了红色边框的功能,而不需要改变 Circle 类的代码。
装饰者模式的优点在于它能够灵活地扩展对象的功能,而不需要修改现有的代码,同时遵循了开放-封闭原则。但是,过度使用装饰者模式可能会导致系统中出现大量的小类,增加复杂性。因此,在使用装饰者模式时需要权衡利弊。
相关文章:
装饰者模式(设计模式)
装饰模式就是对一个类进行装饰,增强其方法行为,在装饰模式中,作为原来的这个类使用者还不应该感受到装饰前与装饰后有什么不同,否则就破坏了原有类的结构了,所以装饰器模式要做到对被装饰类的使用者透明,这…...
ADB调试命令大全
目录 前言命令大全1.显示当前运行的全部模拟器:adb devices2.启动ADB: adb start-server3.停止ADB: adb kill-server4.安装应用程序: adb install -r [apk文件]5.卸载应用程序: adb uninstall [packagename]6.将手机设备中的文件copy到本地计…...
查看npm版本异常,更新nvm版本解决问题
首先说说遇见的问题,基本上把nvm,npm的坑都排了一遍 nvm版本导致npm install报错 Unexpected token ‘.‘install和查看node版本都正确,结果查看npm版本时候报错 首先就是降低node版本… 可以说基本没用,如果要降低版本的话&…...
计算机行业
计算机行业环境分析 2022.01.12 计算机行业环境分析 计算机专业就业前景 随着科技的进步和信息事业的发展,尤其是计算机技术的发展与网络应用的逐渐普及。计算机已成为人们工作和生活中不可缺少的东西。IT行业迅猛发展,就业工作岗位也比比皆是。在最近…...
各种机器学习算法的应用场景分别是什么(比如朴素贝叶斯、决策树、K 近邻、SVM、逻辑回归最大熵模型)?
2023简直被人工智能相关话题席卷的一年。关于机器学习算法的热度,也再次飙升,网络上一些分享已经比较老了。那么今天借着查询和学习的机会,我也来浅浅分享下目前各种机器学习算法及其应用场景。 为了方便非专业的朋友阅读,我会从算…...
SQLite JDBC驱动程序
SQLite JDBC驱动程序下载地址: 下载地址...
Postgre 调优工具pgBadger部署
一,简介: pgBadger(日志分析器)类似于oracle的AWR报告(基于1小时,一天,一周,一月的报告),以图形化的方式帮助DBA更方便的找到隐含问题。 pgbadger是为了提高…...
【云原生】Kubernetes----Helm包管理器
目录 引言 一、Helm概述 1.Helm价值概述 2.Helm的基本概念 3.Helm名词介绍 二、安装Helm 1.下载二进制包 2.部署Helm环境 3.添加补全信息 三、使用Helm部署服务 1.创建chart 2.查看文件信息 3.安装chart 4.卸载chart 5.自定义chart服务部署 6.版本升级 7.版本…...
Bootstrap 5 进度条
Bootstrap 5 进度条 引言 Bootstrap 5 是目前最流行的前端框架之一,它提供了一套丰富的组件和工具,帮助开发者快速构建响应式、移动设备优先的网页。在本文中,我们将重点探讨 Bootstrap 5 中的进度条组件,包括其基本用法、定制选…...
MySQL查询数据库中所有表名表结构及注释以及生成数据库文档
MySQL查询数据库中所有表名表结构及注释 生成数据库文档在后面!!! select t.TABLE_COMMENT -- 数据表注释 , c.TABLE_NAME -- 表名称 , c.COLUMN_COMMENT -- 数据项 , c.COLUMN_NAME -- 英文名称 , -- 字段描述 , upper(c.DATA_TYPE) as …...
Redis缓存穿透、缓存雪崩和缓存击穿的解决方案
Redis缓存穿透、缓存雪崩和缓存击穿的解决方案 引言 Redis作为当前非常流行的内存数据结构存储系统,以其高性能和灵活性被广泛应用于缓存、消息队列、排行榜等多种场景。然而,在实际使用过程中,可能会遇到缓存穿透、缓存雪崩和缓存击穿等问…...
如何解决javadoc一直找不到路径的问题?
目录 一、什么是javadoc二、javadoc为什么会找不到路径三、如何解决javadoc一直找不到路径的问题 一、什么是javadoc Javadoc是一种用于生成Java源代码文档的工具,它可以帮助开发者生成易于阅读和理解的文档。Javadoc通过解析Java源代码中的注释,提取其…...
redis 笔记2之哨兵
文章目录 一、哨兵1.1 简介1.2 实操1.2.1 sentinel.conf1.2.2 问题1.2.3 哨兵执行流程和选举原理1.2.4 使用建议 一、哨兵 1.1 简介 上篇说了复制,有个缺点就是主机宕机之后,从机只会原地待命,并不能升级为主机,这就不能保证对外…...
LVS+Keepalived NGINX+Keepalived 高可用群集实战部署
Keepalived及其工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题。 VRRP协议(虚拟路由冗余协议) 是针对路由器的一种备份解决方案由多台路由器组成一个热备组,通过共用的…...
Mybatis做批量操作
动态标签foreach,做过批量操作,但是foreach只能处理记录数不多的批量操作,数据量大了后,先不说效率,能不能成功操作都是问题,所以这里讲一讲Mybatis正确的批量操作方法: 在获取opensession对象…...
Python | 中心极限定理介绍及实现
统计学是数据科学项目的重要组成部分。每当我们想从数据集的样本中对数据集的总体进行任何推断,从数据集中收集信息,或者对数据集的参数进行任何假设时,我们都会使用统计工具。 中心极限定理 定义:中心极限定理,通俗…...
探索Napier:Kotlin Multiplatform的日志记录库
探索Napier:Kotlin Multiplatform的日志记录库 在现代软件开发中,日志记录是不可或缺的部分,它帮助开发者追踪应用的行为和调试问题。对于Kotlin Multiplatform项目而言,能够在多个平台上统一日志记录的方法显得尤为重要。Napier…...
MySQL基础——SQL语句
目录 1.SQL通用语法 2.SQL分类 3 DDL 3.1数据库操作 3.1.1查询 3.1.2创建 3.1.3删除 3.1.4使用 3.2表操作 3.2.1查询 3.2.2创建 3.2.3数据类型 3.2.4表修改(alter打头) 3.2.5表删除(drop/truncate打头) 3.3 DDL总结…...
比特币通用API服务
Bitcoin 通用API服务 exlectrs: API后台服务(Rust语言编写) https://github.com/Blockstream/electrs.git 使用electr作为后台的区块链浏览器:https://github.com/Blockstream/esplora.git https://github.com/Blockstream/electrs https://github.com/romanz/electrs/blo…...
Spock mock私有方法
mock私有方法 被测试的方法是MiddleGroundAppListBO类下的getPromptIdKeyAppPromptInfoMap方法 private Map<Long, AppPromptInfoModel> getPromptIdKeyAppPromptInfoMap(String cubeAppIdentity) {List<AppPromptInfoDO> promptByApp knowledgeCubeQueryR…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
