装饰器模式、代理模式、适配器模式对比

装饰器模式、代理模式和适配器模式都是结构型设计模式,它们的主要目标都是将将类或对象按某种布局组成更大的结构,使得程序结构更加清晰。这里将装饰器模式、代理模式和适配器模式进行比较,主要是因为三个设计模式的类图结构相似度较高、且功能上存在一定的相似度。接下来将一步步说明。

装饰器模式

装饰器模式是一种结构型设计模式,用来动态地给一个对象增加一些额外的职责,即增加该对象额外的功能,其别名为包装器(Wrapper)。在装饰器模式中,会定义一个装饰器类,声明了一个指向被封装对象的引用成员变量,并定义了可动态添加到被封装对象的具体行为。其类图表示如下:

请添加图片描述

从类图结构上来说,装饰器模式并没有直接修改对象,而是在不影响对象的情况下,以动态、透明的方式给单个对象添加职责。就增加对象功能来说,装饰器模式比生成子类实现更为灵活。
装饰器模式主要适用于需要给对象动态地增加一些额外职责的场景。装饰器能将业务逻辑组织为层次结构,开发者可为各层创建一个装饰器,在运行时将各种不同逻辑组合成对象。特别是当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时,可以考虑使用装饰器模式。不能采用继承的情况主要有三类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如final类);第三类是需要扩展的类来源于三方件,对于三方件的代码,如无特殊说明,是不建议使用继承来扩展功能的。
由于被装饰对象和装饰对象可以独立变化,用户可以根据需要增加新的被装饰类和装饰类,原有代码无须改变,这符合"开闭原则"。相比通过继承关系扩展对象的功能,装饰器模式可以提供比继承更多的灵活性,可以在不创建新子类的前提下,扩展对象的行为。但是,装饰器也带来代码复杂度上升的问题。使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。此外,装饰器模式比继承更加灵活,也同时意味着装饰器模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

代理模式

代理模式是一种结构型设计模式,用来为一个对象提供一种代理以控制对该对象的访问,即通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。代理对象控制着对于原对象的访问,并允许在将请求提交给原对象前后进行一些处理。为使用代理对象控制对原对象的访问,需要创建一个代理类并封装对原对象的访问。其类图表示如下:

请添加图片描述

代理模式适用于各种需要代理的场景,如远程代理、虚拟代理、缓存代理、动态代理等等。以动态代理为例,对于基于Spring框架开发的应用来说,Spring提供的AOP功能,可以看成是动态代理的一种应用。AOP通过切面的设计,可以在不影响对象的前提下,动态的增加代理完成对象的功能增加。
代理模式,在访问对象时引入了一定程度的间接性。因为可以在不对原对做出修改的情况下创建新代理,所以代理模式符合开闭原则。但代理模式的设计,也带来了代码复杂度上升的问题。实现代理模式需要额外的工作,有些代理模式的实现非常复杂(如动态代理)。此外,由于在客户端和真实对象之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,从而带来服务响应的延迟。但是,这部分影响是极小的。
从类图结构上来说,装饰器模式和代理模式的相似度极高,但是两者还是有一定的差异。如果说装饰器模式的重心是动态地给对象增加一些职责模式,那么代理模式的重心则是通过代理对象间接地访问实际对象,并在代理过程中添加一些额外的逻辑或控制。代理模式主要应用于对象访问困难或复杂、或无法直接访问等场景。简言之,装饰器模式主要关注增强对象的功能,而代理模式则更多关注对对象访问的控制,并不直接增强对象的功能。

适配器模式

适配器模式是一种结构型设计模式,用于将一个类的接口转换成用户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器。根据适配器是根据继承方式,还是组合方式和待适配的类进行交互,可以将
适配器模式分为对象适配器和类适配器两种实现。对象适配器类图表示如下:

请添加图片描述

类适配器类图表示如下:

请添加图片描述

从类图结构上可以看到,对象适配器和类适配器的唯一差别就是适配器类(Adapter)和待适配类(Adaptee)的关系。对于类适配器来说,适配器类作为待适配类的子类,对原有方法进行了重写。而对于对象适配器来说,适配器类将待适配器类作为其成员,通过调用待适配器类的接口,完成了原有方法的重写。在实际的应用中,对于需要使用适配器的场景,应优先选用对象适配器。只有在对象适配器不合适的场景下,才考虑使用类适配器。如需要复用这样一些类,他们处于同一个继承体系,并且他们又有了额外的一些共同的方法,这时类适配器就比对象适配器更适合。
适配器模式主要适用于需要使用某个现有类,但是这个现有类的接口不符合系统的需要,或想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类一起工作等场景。适配器模式通过创建一个中间层类,可将其作为代码与遗留类、第三方类或提供接口的类之间的转换器。
适配器可以让接口不兼容的对象相互合作。通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码,实现了目标类和适配者类的解耦。且可以将接口或数据转换代码从目标类主要业务逻辑中分离出来,符合单一职责原则。但是,适配器模式也带来了代码整体复杂度上升的问题,开发者需要新增一系列接口和类。
适配器模式和装饰器模式都被称为包装器,但是两者适用的场合不同。适配器模式的主要目的是将一个类的接口转换成客户端所期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起协作。装饰器模式则是强调给对象增加一些新的行为或责任。适配器模式重点关注接口转换和兼容性,而装饰器模式则重点关注为对象动态地添加新的行为或责任。

装饰器模式、代理模式和适配器模式对比

无论装饰模式、代理模式和适配器模式,都是结构型设计模式。其主要职责都是将将类或对象按某种布局组成更大的结构,使得程序结构更加清晰。从类图结构上来说,装饰器模式和代理模式和对象适配器的结构上差异不大,都是通过一个外部类去组合目标类,并封装其行为。从功能上来说,装饰器模式关注的是给对象增加一些新的行为或责任。相比基于继承关系扩展对象的功能,装饰器模式可以提供比继承更多的灵活性,可以在不创建新子类的前提下,扩展对象的行为。代理模式更多的关注对象访问的控制,并不直接增强对象的功能。通过代理对象间接地访问实际对象,并在代理过程中添加一些额外的逻辑或控制。而适配器模式则关注接口转换或接口兼容性。通过将一个类的接口转换成客户端所期望的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的类可以一起协作。
在实际的应用中,针对装饰器模式、代理模式和适配器模式的选用上,还是要从功能上出发,因为三个设计模式在类图结构上差异并不大。通过其应用场景选择合适的设计模式,如对于对象功能增强的场景,选用装饰器模式,对于对象访问控制的场景,选用代理模式,对于接口的转换或兼容的场景,选用适配器模式。

参考

https://yiyan.baidu.com/ 文心一言
https://blog.csdn.net/kingmax54212008/article/details/107294704 OOAD-设计模式(四)结构型模式之适配器、装饰器、代理模式

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VitePress 构建的博客如何部署到 github 平台?

VitePress 构建的博客如何部署到 github 平台? 1. 新建 github 项目 2. 构建 VitePress 项目 2.1. 设置 config 中的 base 由于我们的项目名称为 vite-press-demo,所以我们把 base 设置为 /vite-press-demo/,需注意前后 / export default…

Docker容器:搭建LNMP架构

目录 前言 1、任务要求 2、Nginx 镜像创建 2.1 建立工作目录并上传相关安装包 2.2 编写 Nginx Dockerfile 脚本 2.3 准备 nginx.conf 配置文件 2.4 生成镜像 2.5 创建 Nginx 镜像的容器 2.6 验证nginx 3、Mysql 镜像创建 3.1 建立工作目录并上传相关安装包 3.2 编写…

java案例-读取xml文件

需求 导入依赖 <dependencies><!-- dom4j --><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency> </dependencies>代码 SAXReader saxReade…

进迭时空宣布开源RISC-V芯片的AI核心技术

仟江水商业电讯&#xff08;4月29日 北京 委托发布&#xff09;4月29日&#xff0c;在“创芯生生不息——进迭时空2024年度产品发布会”上&#xff0c;进迭时空CEO、创始人&#xff0c;陈志坚博士宣布将开源进迭时空在自研RISC-V AI CPU上的核心技术&#xff0c;包括AI扩展指令…

无人机+集群组网+单兵图传:空地一体化组网技术详解

空地一体化组网技术是一种结合了无人机、集群自组网和单兵图传等多种技术的先进通信解决方案。这种技术方案的主要目的是在前线事故现场和后方指挥中心之间建立一个高效、稳定的通信链路&#xff0c;以确保信息的实时传输和指挥的顺畅进行。 首先&#xff0c;前端视频采集部分&…

自适应信号处理基础及应用——DSP学习笔记五

本专栏的图片内容都来自于老师讲课的PPT&#xff0c;本篇博客只是我个人对于上课内容的知识结构分析和梳理。 导论 自适应系统的定义、特征、形式、举例 特征 非自适应系统 • 固定参数的设计方法 • 假定事先知道了一切可能的输入条件&#xff1b;在这些条件下怎样动作&#…

word 表格 文字 上下居中

问题 word 表格 文字 上下居中 详细问题 笔者进行word 文档编辑&#xff0c;对于表格中的文本内容&#xff0c;如何进行上下居中&#xff1f; 解决方案 步骤1、选中需要进行操作的单元格 步骤2、右键 → \rightarrow →点击表格属性 步骤3、依次点击单元格 → \rightar…

Qt绘图与图形视图之自定义图元实现拖拽、拉伸、旋转功能

往期回顾 Qt绘图与图形视图之移动鼠标手动绘制任意多边形的简单介绍-CSDN博客 Qt绘图与图形视图之场景、视图架构的简单介绍-CSDN博客 Qt绘图与图形视图之基本图元绘制的简单介绍-CSDN博客 Qt绘图与图形视图之自定义图元实现拖拽、拉伸、旋转功能 一、最终效果 实现对自定义图…

应用层协议了解

一 HTTP前置知识 这篇博客会有点长&#xff0c;但对我来说非常有意义&#xff0c;这是我从一无所知到理解网络的重大突破&#xff0c;在前两个月我对网络非常恐惧&#xff0c;还十分不理解什么是网络&#xff0c;什么是协议。接下来先介绍几个概念。 1 流量 我们把数据给别人&…

GitHub Desktop进行汉化

第一步下载github桌面版 官网&#xff1a;安装 GitHub Desktop - GitHub 文档 历史版本&#xff1a;https://github.cn.uptodown.com/windows/versions 本期下载版本3.3.11进行汉化&#xff0c;最新版不一定稳定。 网站打不开的可自取&#xff1a; 3.3.11版本安装包链接&a…

【论文笔记】Language Models are Few-Shot Learners B部分

Language Models are Few-Shot Learners B 部分 回顾一下第一代 GPT-1 &#xff1a; 设计思路是 “海量无标记文本进行无监督预训练少量有标签文本有监督微调” 范式&#xff1b;模型架构是基于 Transformer 的叠加解码器&#xff08;掩码自注意力机制、残差、Layernorm&#…

排序算法:插入、希尔、选择、推排、冒泡、快速、归并排序

排序算法 目录 前言 一、排序的概念 1.1排序的概念 1.2 常见的排序算法 二、常见排序算法的实现 2.1 插入排序 2.2 希尔排序 2.3 选择排序 2.4 堆排序 2.5 冒泡排序 2.6 快速排序 2.6.1 hoare版本 2.6.2 前后指针版本 2.6.3 非递归版本 2.7 归并排序 归并排序 2.8 计数排序 三、…

【mysql】mysql中的数据类型知多少?

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

在VMware中如何快速克隆出一台虚拟机

鉴于经常需要使用新开虚拟机出来给开发团队用于测试部署&#xff0c;之前没有克隆功能之前都是需要一台装一个操作系统&#xff0c;无论是linux、windows server版或 windows 10 版&#xff0c;整个安装过程下来还是要一个来小时。后来做了装了十多次以后&#xff0c;想着试一下…

《微服务设计》读书笔记

此为阅读纽曼《微服务设计》一书后总结的读书笔记&#xff0c;点此处下载PDF文档。 一、微服务的概念 微服务&#xff08;或称微服务架构&#xff09;是一种云原生架构方法&#xff0c;其核心思想在于将单个应用拆分为众多 小型、松散耦合的服务&#xff0c;服务之间均通过网…

利用Triple U.Net结构对冷冻切片HE染色组织学图像进行核实例分割

利用Triple U.Net结构对冷冻切片H&E染色组织学图像进行核实例分割 摘要IntroductionRelated WorksDatasetProposed MethodologyDataset PreparationSegmentation BranchLoss FunctionWatershed Algorithm Nuclei Instance Segmentation of Cryosectioned H&E Stained H…

基于Springboot的校园博客系统

基于SpringbootVue的校园博客系统 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 文章信息 系统公告 后台登录 后台首页 博主管理 文章分类管理 文章信息管理 举报投诉管…

网络编程——TCP

socket socket类型 流式套接字(SOCK_STREAM) TCP 提供了一个面向连接、可靠的数据传输服务&#xff0c;数据无差错、无重复、无丢失、无失序的发送且按发送顺序接收。内设置流量控制&#xff0c;避免数据流淹没慢的接收方。数据被看作是字节流&#xff0c;无长度限制。 数据报…

IDEA新版本创建Spring项目只能勾选17和21却无法使用Java8的完美解决方案

想创建一个springboot的项目&#xff0c;使用Spring Initializr创建项目时&#xff0c;发现版本只有17&#xff5e;21&#xff0c;无法选择Java8。 我们知道IDEA页面创建Spring项目&#xff0c;其实是访问spring initializr去创建项目。我们可以通过阿里云国服间接创建Spring项…

【UE5】动态播放媒体

最近项目中有一个需求&#xff0c;需要将场景中的42块屏幕都显示媒体内容&#xff0c;想着如果每一块屏幕都创建一个MediaPlayer资产、一个MediaSource资产、一个MediaTexture资产及创建对应的Material&#xff0c;就是4*42168个资产需要维护了&#xff0c;所以想着就全部采用动…