设计模式探索:装饰器模式

1. 装饰器模式定义

装饰器模式(Decorator Pattern)

装饰器模式是一种结构型设计模式,允许向一个对象动态添加行为。在不改变类的接口的情况下,装饰器模式在原始类上增加额外的职责,并且支持多个装饰器嵌套使用。
在这里插入图片描述

装饰器模式代码示例

抽象构件类

/*** 抽象构件类* 该类声明了具体构件和装饰类中实现的业务方法,使得客户端能以一致的方式处理未装饰和已装饰对象。*/
public abstract class Component {// 抽象方法,由具体构件和装饰类实现public abstract void operation();
}

具体构件类

/*** 具体构件类* 该类实现了抽象构件类的业务方法,是被装饰的对象。*/
public class ConcreteComponent extends Component {@Overridepublic void operation() {System.out.println("ConcreteComponent: 基础功能实现");}
}

抽象装饰类

/*** 抽象装饰类* 该类是装饰者模式的核心,继承了抽象构件类,并持有一个抽象构件类型的对象引用。*/
public abstract class Decorator extends Component {// 维持一个对抽象构件对象的引用protected Component component;// 注入一个抽象构件类型的对象public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {// 调用原有业务方法component.operation();}
}

具体装饰类

/*** 具体装饰类* 该类是装饰者模式的具体实现类,向构件添加新的职责。*/
public class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}@Overridepublic void operation() {super.operation(); // 调用原有业务方法addedBehavior(); // 调用新增业务方法}// 新增业务方法public void addedBehavior() {System.out.println("ConcreteDecorator: 新增业务功能");}
}

客户端使用示例

public class Client {public static void main(String[] args) {// 创建具体构件对象Component component = new ConcreteComponent();// 使用装饰类进行装饰Component decoratedComponent = new ConcreteDecorator(component);// 调用装饰后的方法decoratedComponent.operation();}
}

输出结果

ConcreteComponent: 基础功能实现
ConcreteDecorator: 新增业务功能

解析

  • 抽象构件类(Component):声明了具体构件和装饰类中实现的业务方法,使得客户端能以一致的方式处理未装饰和已装饰对象。
  • 具体构件类(ConcreteComponent):实现了抽象构件类的业务方法,是被装饰的对象。
  • 抽象装饰类(Decorator):继承了抽象构件类,持有一个抽象构件类型的对象引用,并实现了业务方法,通过调用引用对象的方法实现对业务方法的调用。
  • 具体装饰类(ConcreteDecorator):继承了抽象装饰类,实现了新增的业务方法。

通过这种设计模式,装饰器可以在不修改原始类代码的情况下,为原始类添加新的功能,并且支持多个装饰器的嵌套使用,从而灵活地增强原始类的功能。

2. 装饰器模式与代理模式的区别

代理模式(Proxy Pattern)

代理模式也是一种结构型设计模式,为其他对象提供一个代理,以控制对这个对象的访问。代理模式的主要目的是控制访问,而非增强功能。
在这里插入图片描述

  1. 目的意图不同

    • 装饰器模式:主要是为了增强目标类的功能。
    • 代理模式:主要是为了控制对目标类的访问。
  2. 使用差别

    • 装饰器模式:装饰器对目标对象没有控制权,目标对象的方法一定会被执行。
    • 代理模式:代理对象对目标对象有控制权,可以选择执行或不执行目标对象的方法。
  3. 对于客户端的关注点

    • 装饰器模式:客户端更关心的是对目标对象进行增强后的功能。
    • 代理模式:客户端更关心的是被代理对象的功能。

3. 装饰器模式在实际开发中的应用

**需求:**有多个装饰时是怎么保证后面的装饰,在前面装饰的基础上装饰的。比如字符,需要加密+压缩。怎么能让压缩,在加密的基础上压缩?

3.1 创建字符组件接口

public interface StringComponent {String transform(String str);
}

3.2 实现字符组件

// 字符组件
public class StringEncryptor implements StringComponent {@Overridepublic String transform(String str) {// base64编码return Base64.getEncoder().encodeToString(str.getBytes());}
}

3.3 字符加密装饰器

public class StringEncryptorDecorator implements StringComponent {private StringComponent component;public StringEncryptorDecorator(StringComponent component) {this.component = component;}@Overridepublic String transform(String str) {String encrypted = component.transform(str); // 调用前面一个装饰器或组件的方法// 这里演示一个简单的压缩方法,将字符串压缩成一行return encrypted.replaceAll("\\s+", "");}
}

3.4 字符压缩的装饰器

public class StringCompressorDecorator implements StringComponent {private StringComponent component;public StringCompressorDecorator(StringComponent component) {this.component = component;}@Overridepublic String transform(String str) {String compressed = component.transform(str); // 调用前面一个装饰器或组件的方法// 这里演示一个简单的压缩方法,将字符串压缩成一行return compressed.replaceAll("\\s+", "");}
}

3.5 客户端

public class Client {public static void main(String[] args) {StringComponent component = new StringEncryptor(); // 创建字符加密组件component = new StringEncryptorDecorator(component); // 用字符加密装饰器装饰它component = new StringCompressorDecorator(component); // 用字符压缩装饰器再次装饰它String original = "Hello, world!"; // 原始字符串String transformed = component.transform(original); // 转换后的字符串System.out.println(transformed);}
}

输出结果为:SGVsbG8sIHdvcmxkIQ==,这是对原始字符串进行加密和压缩后的结果。可以看到,压缩操作在加密操作的基础上进行了。

4. 装饰器模式总结

装饰器模式概述

装饰器模式是一种结构型设计模式,旨在动态地给对象添加额外的职责。

优点:

  1. 灵活性: 装饰器模式允许在运行时通过添加装饰器来扩展对象的功能,比静态继承更加灵活。
  2. 可扩展性: 可以对一个对象进行多次装饰,以实现不同的行为或功能。
  3. 低耦合度: 装饰器模式允许开发者在不修改对象本身的情况下增加新功能。
  4. 开闭原则: 符合开闭原则,即对扩展开放,对修改封闭。

缺点:

  1. 对象数量多: 装饰器模式可能会产生许多小的装饰器对象,增加系统的复杂性。
  2. 错误机会多: 由于装饰器数量可能很多,增加了出错的机会。
  3. 性能问题: 装饰器模式可能会引入额外的性能开销,尤其是在多层装饰的情况下。

适用场景:

  1. 动态添加职责: 当需要动态地给对象添加职责,而不是通过继承增加子类。
  2. 透明性: 需要保持对象的接口不变,即装饰前后对象的接口完全一致。
  3. 不支持继承: 在不支持或不便于使用继承来扩展功能的场景。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

车载聚合路由器应用场景分析

乾元通QYT-X1z车载式1U多卡聚合路由器,支持最多8路聚合,无论是应急救援,还是车载交通,任何宽带服务商无法覆盖的区域,聚合路由器可提供现场需要的稳定、流畅、安全的视频传输网络,聚合路由器可无缝接入应急…

安装nodejs | npm报错

nodejs安装步骤: 官网:https://nodejs.org/en/ 在官网下载nodejs: 双击下载下来的msi安装包,一直点next,我选的安装目录是默认的: 测试是否安装成功: 输入cmd打开命令提示符,输入node -v可以看到版本,说…

idea创建dynamic web project

由于网课老师用的是eclipse,所以又得自己找教程了…… 解决方案: https://blog.csdn.net/Awt_FuDongLai/article/details/115523552

有没有适合全体质猫咪的主食冻干?全价冻干:希喂大橙罐实测分享

作为一个注重猫咪身体健康和幸福感的铲屎官,怎么会不喂主食冻干。毕竟,除了猫咪爱吃外,高含肉量、高营养的主食冻干也能给猫咪的健康带来一系列的好处。 最近,我给我家猫猫们入手了一款性价比超高的主食冻干:希喂CPMR2…

mybatis中的标签

在MyBatis中&#xff0c;除了基本的SQL映射功能外&#xff0c;还有许多用于动态SQL构建的标签。这些标签允许我们根据不同的条件和需求构建复杂的SQL语句。主要的动态SQL标签包括<if>, <choose>, <when>, <otherwise>, <trim>, <set>, <…

deepstream段错误

&#x1f610; 错误&#xff1a; 探针中由于使用了pyds.get_nvds_buf_surface(hash(gst_buffer), frame_meta.batch_id)导致的段错误&#xff08;segmentation fault&#xff09;。 解决方式&#xff1a;

彩带插画:成都亚恒丰创教育科技有限公司

彩带插画&#xff1a;色彩斑斓的艺术世界 在浩瀚的艺术海洋中&#xff0c;彩带插画以其独特的魅力&#xff0c;如同一条绚烂的彩绸&#xff0c;轻轻拂过人们的心田&#xff0c;留下一抹抹难以忘怀的色彩。成都亚恒丰创教育科技有限公司它不仅仅是一种视觉上的享受&#xff0c;…

二叉树超详细解析

二叉树 目录 二叉树一级目录二级目录三级目录 1.树的介绍1.1树的定义1.2树的基本术语1.3相关性质 2.二叉树介绍2.1定义2.2 性质 3.二叉树的种类3.1 满二叉树3.2完全二叉树3.3 二叉查找树特点&#xff1a;二叉查找树的节点包含的基本信息&#xff1a; 3.4 平衡二叉树 4.二叉树的…

python破解密码·筛查和选择

破解密码时可能遇到的几种情况 ① 已知密码字符&#xff0c;破排序 ② 已知密码位数&#xff0c;破字符 ③ 已知密码类型&#xff0c;破字位 ④ 已知部分密码&#xff0c;破未知 ⑤ 啥都不知道&#xff0c;盲破&#xff0c;玩完 ⑥ 已知位数、字符、类型、部分密码中的几个&am…

单链表(C语言详细版)

1. 链表的概念及结构 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表的结构跟火车车厢相似&#xff0c;淡季时车次的车厢会相应减少&#xff0c;旺季时车次的车厢会额外增加几节。…

资料分析笔记整理

提升技巧多做题、少动笔、多分析 资料分析认识 国考一般20题(24~28分钟) 统计材料的类型包括单纯的文字、表格、图形以及由这些元素组成的复合类型材料 文字性材料:(30~60秒) 多段落型文字材料(时间、关键词、结构) 孤立段落文字材料(时间、关键词、标点[。;]) 表…

VMware vSAN替换存储解决方案如何选择?

What is vSAN &#xff1f; 是一款软件定义的企业存储解决方案&#xff0c;支持超融合基础架构系统。vSAN与VMware vSphere 完全集成在一起&#xff0c;作为ESXi Hypervisor内的分布式软件层&#xff0c;通过整合、池化ESXi各个主机上的存储资源&#xff0c;为vSphere虚拟化平…

施罗德数列SQL实现

在组合数学中,施罗德数用来描述从(0,0)到(n,n)的格路中,只能使用(1,0)、(0,1)、(1,1)三种移动方式,始终位于对角线下方且不越过对角线的路径数 DECLARE n INT 10 DECLARE i INT DECLARE rst INT DECLARE old INT1CREATE TABLE #rst (i INT ,rst int )INSERT INTO #rst values(…

数据结构双向循环链表

主程序 #include "fun.h" int main(int argc, const char *argv[]) { double_p Hcreate_head(); insert_head(H,10); insert_head(H,20); insert_head(H,30); insert_head(H,40); insert_tail(H,50); show_link(H); del_tail(H); …

UE5.3-基础蓝图类整理一

常用蓝图类整理&#xff1a; 1、获取当前关卡名&#xff1a;Get Current LevelName 2、通过关卡名打开关卡&#xff1a;Open Level(by name) 3、碰撞检测事件&#xff1a;Event ActorBeginOverlap 4、获取当前player&#xff1a;Get Player Pawn 5、判断是否相等&#xff1…

回溯算法-以学生就业管理系统为例

1.回溯算法介绍 1.来源 回溯算法也叫试探法&#xff0c;它是一种系统地搜索问题的解的方法。 用回溯算法解决问题的一般步骤&#xff1a; 1、 针对所给问题&#xff0c;定义问题的解空间&#xff0c;它至少包含问题的一个&#xff08;最优&#xff09;解。 2 、确定易于搜…

可视化作品集(09):可视化运维大屏不可或缺。

可视化大屏在可视化运维上有很多价值&#xff0c;而且应用十分普遍&#xff0c;本文给老铁们分享一下。 1. 实时监控&#xff1a;可视化大屏可以实时展示系统运行状态、设备状态、生产数据等信息&#xff0c;使运维人员能够及时发现问题并做出相应的处理。 2. 数据分析&#x…

文件上传漏洞:upload-labs靶场安装和实践

一、upload-labs靶场安装 安装&#xff1a;Windows下的Upload-labs环境搭建(Upload文件夹不存在报错&#xff09;_upload-labs文件夹不存在-CSDN博客 当安装好phpstudy之后&#xff0c;在网址栏输入&#xff1a;localhost或127.0.0.1&#xff0c;如果没问题&#xff0c;就将下…

鸿蒙系统创建签名文件及使用创建签名文件打包并安装

* 第一步 第二步&#xff1a;创建.p12文件&#xff0c;点击New如果有的话就Choose Existing 填好下面信息 点击Next进入到下面界面 开始生成csr文件如下图 点击OK–>Finish 文件保存在了下面目录 第三步 1.访问华为开发者平台&#xff0c;登录开发者账号&#xff0c;进…

影视行业的人工智能与-【机器学习】:案例分析

欢迎关注小知&#xff1a;知孤云出岫 目录 引言AI和ML在影视行业的当前应用AI和ML对影视行业的未来影响案例研究&#xff1a;AI生成动画视频目标工具和库数据收集模型训练视频生成 结论参考文献 引言 人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09…