首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

设计模式:代理、装饰和适配器模式的区别

编程知识
2024年07月28日 17:14

结构对比

讲实话,博主当初学习完整设计模式时,这三种设计模式单独摘哪一种都是十分清晰和明确的,但是随着模式种类的增加,在实际使用的时候竟然会出现恍惚,例如读开源代码时,遇到不以模式命名规范的代码时,一时难以说清具体是使用的这三种里的哪一种。

之所以会出现混淆的原因是,三种模式的实现都是基于面向接口这一思想,三种模式都是针对某一个具体的接口实现,并在其实现类上用一个对象对另一个对象提供间接访问。

基于混淆点,从类图上来看,适配器模式就可以最先被区别出来,适配器的类结构图

从类图上来看,适配器的主角是Adapter这个类,这个类与目标接口是实现关系,但是Adaptee则不同,它可以是一个接口,也可以是一个具体的类,它是与Target平级的一个对象,与Target毫无关系,而Adapter与它的关系是对象组合,是Adaptee作为Adapter的一个内部成员变量,Adapter的目的是将 Adaptee适配为Target。

相比于适配器模式,代理模式和装饰模式反而更容易被混淆, 混淆的原因是二者都是基于一个公共接口,且主角类(Proxy和Decorator)又都是以组合对象的形式,对目标对象(RealSubject和ConcreteComponent)进行二次操作。实现上来看,两者十分相似。

但是注意,这里还是有不同,

  • 代理模式是代理对象(Proxy)对实际被代理对象(RealSubject)的间接访问,是对公共接口的实现类提供间接访问;
  • 而装饰模式的装饰类是对被装饰接口或者说被装饰基类(Component)提供间接访问,不是对接口(Component)的实现类提供间接访问

也就是说,两者提供间接访问的对象不同,一个(代理模式)是基于具体的类,而另一个(装饰模式)是基于抽象的接口 。这也是为什么只可以使用一次的request对象要基于装饰模式提供封装来达到二次使用的原因(详细可翻阅设计模式:从HttpServletRequestWrapper了解装饰者模式),基于抽象接口提供的间接访问是不会破坏具体对象的内容。

本质对比

适配器模式的本质

适配器模式的主要功能是进行转换匹配,目的是复用已有的功能,而不是来实现新的接口。也就是说,客户端需要的功能应该是已经实现好了的,不需要适配器模式来实现,适配器模式主要负责把不兼容的接口转换成客户端期望的样子就可以了。

适配器的本质是转换功能,以提高复用性。不同于代理和装饰,适配器中的目标对象可能与需要适配的对象毫无关系,适配过程中代码甚至是全量的重写,它的目标是将两个内容沿其中某个为主进行融合。

代理模式的本质

代理模式是通过创建一个代理对象,用这个代理对象去代表真实的对象,客户端得到这个代理对象后,对客户端并没有什么影响,就跟得到了真实对象一样来使用。当客户端操作这个代理对象的时候,实际上功能最终还是会由真实的对象来完成,只不过是通过代理操作的,也就是客户端操作代理,代理操作真正的对象。
正是因为有代理对象夹在客户端和被代理的真实对象中间,相当于一个中转,那么在中转的时候就有很多花招可以玩,比如,判断一下权限,如果没有足够的权限那就不进行中转了,或者中转到别的操作中。

代理模式的运行逻辑:

代理模式的本质是控制对象访问。核心在于Proxy角色, 类似于中间商,是目标对象的一个“前沿发言人”,你想要访问目标对象,或者购买目标厂家的商品,必须从我代理商这里走, 我甚至可以不创建被代理对象,自己冒充被代理对象(直接以贴牌产品当作目标产品卖你)。

装饰模式的本质

装饰模式能够实现动态地为对象添加功能,是从一个对象外部来给对象增加功能,相当于是改变了对象的外观。当装饰过后,从外部使用系统的角度看,就不再是使用原始的那个对象了,而是使用被一系列的装饰器装饰过后的对象。这样就能够灵活地改变一个对象的功能,只要动态组合的装饰器发生了改变,那么最终所得到的对象的功能也就发生了改变。从这一点上来讲,代理模式也可以满足,但是不同的是,装饰模式这里有一个代理无法越过的原则,那就是代理模式必须有目标对象,否则装饰就无从谈起。

装饰模式的本质是通过组合来加强目标对象的能力,是对象能力的延申。装饰模式是在原有对象的基础上进行外层包装,可以对目标对象的每一个方法都进行前置、后置的补充和加强,但是本质上并没有改变原对象,是一种扩展思维,这一点可以参考AOP的思想。

 

From:https://www.cnblogs.com/TheGCC/p/18328628
本文地址: http://shuzixingkong.net/article/525
0评论
提交 加载更多评论
其他文章 Nuxt.js 路由管理:useRouter 方法与路由中间件应用
title: Nuxt.js 路由管理:useRouter 方法与路由中间件应用 date: 2024/7/28 updated: 2024/7/28 author: cmdragon excerpt: 摘要:本文介绍了Nuxt 3中useRouter方法及其在路由管理和中间件应用中的功能。内容包括
Nuxt.js  路由管理:useRouter 方法与路由中间件应用 Nuxt.js  路由管理:useRouter 方法与路由中间件应用
Jenkins如何使用CrumbIssuer防御CSRF攻击
1、CSRF(跨站请求伪造)概述 在讲解Jenkins的跨站请求伪造(CSRF)保护机制之前,让我们首先对CSRF这一安全威胁及其重要性进行简明扼要的概述。 1.1 CSRF(跨站请求伪造)的原理 CSRF(即跨站请求伪造)是指利用受害者尚未失效的身份认证信息、(cookie、会话等),诱骗其点击恶
Jenkins如何使用CrumbIssuer防御CSRF攻击 Jenkins如何使用CrumbIssuer防御CSRF攻击 Jenkins如何使用CrumbIssuer防御CSRF攻击
ComfyUI插件:ComfyUI Impact 节点(二)
前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器、细节强化器、预览桥、通配符、Hook、图片发送器、图片接收器等等。通过这些节点的组合运用,我们可以实现的工作有很多,例如自动人脸检测和优化修复、区域增强、
ComfyUI插件:ComfyUI Impact 节点(二) ComfyUI插件:ComfyUI Impact 节点(二) ComfyUI插件:ComfyUI Impact 节点(二)
DP进阶合集
(ps:本集合为Star_F总结的dp进阶知识,持续更新~。 转载本文章需要联系我,否则视为侵权!!) 前置知识:线性dp,背包,树形dp,区间dp 内容预览: 状压dp 数位dp dp优化(前缀和,单调队列,斜率优化) 1. 状压dp: 思路:如果题目中 \(n\) 的范围特别小(\(<=2
Linux Kernel CFI机制简介及测试禁用
PS:要转载请注明出处,本人版权所有。 PS: 这个只是基于《我自己》的理解, 如果和你的原则及想法相冲突,请谅解,勿喷。 环境说明 无 前言 当我们为android移植linux的驱动程序的时候,总会遇到一些错误,这些错误有一部分就是android 内核开启的安全的机制导致的。本文就会介绍一种内核
Linux Kernel CFI机制简介及测试禁用 Linux Kernel CFI机制简介及测试禁用 Linux Kernel CFI机制简介及测试禁用
智能家居如何把老款定频空调变成智能“变频”空调#米家#智能家居#HA
背景 最近长沙的天气暴热,室内达到了34-35度,天气预报最高温度上了40度,这么酷热的天气,离开了空调,基本上就是一身汗,全身湿透,特别难受,然后不得不开启家里的一台将近10年的老式定频空调,输入功率970W,OMG,一小时将近一度电,假设一天吹10小时,就是10度电,一个月三十天,10*30=3
智能家居如何把老款定频空调变成智能“变频”空调#米家#智能家居#HA 智能家居如何把老款定频空调变成智能“变频”空调#米家#智能家居#HA 智能家居如何把老款定频空调变成智能“变频”空调#米家#智能家居#HA
Python 代码中的 yield 到底是什么?
在Python编程中,有一个强大而神秘的关键字,那就是yield。初学者常常被它搞得晕头转向,而高级开发者则借助它实现高效的代码。到底yield是什么?它又是如何在Python代码中发挥作用的呢?让我们一起来揭开它的面纱。 Python里的一个非常重要但也颇具迷惑性的关键词——yield。 什么是y
Python 代码中的 yield 到底是什么? Python 代码中的 yield 到底是什么? Python 代码中的 yield 到底是什么?
408数据结构树算法
第四章 树 4.1 二叉树的顺序存储 #define MAXSIZE 16 typedef int ElemType; typedef struct { ElemType data[MAXSIZE]; int size; }Tree; //初始化二叉树 void initTree(Tree&
408数据结构树算法 408数据结构树算法