绝对干货-讲讲设计模式之结构型设计模式

经典的23种设计模式种属于结构型设计模式的是装饰模式,适配器模式,代理模式,组合模式,桥接模式,外观模式,享元模式。

如果说创建型设计模式解决的是创建对象的问题,那么结构型模式就是通过类和对象的组合解决开发过程中的老代码功能扩展,通过代码结构设计降低代码耦合,针对扩展开放,针对改变关闭,新老功能适配,减少递归函数使用,减少内存使用,提高代码性能等等

        废话讲了太多,直接上干货-各结构型设计模式的本质

        首先我想把装饰模式和代理模式放在一起讲

        有没有人发现透明模式的装饰模式和运用组合思想实现的静态代理非常相识,但是本质上有很大区别,这种区别其实也是装饰模式与代理模式的本质区别,其实说到底两者都在给原有代码做功能扩展的事,但是它们所作用的维度不一样,装饰模式(装饰模式要求装饰器和被装饰对象都实现相同的接口或抽象类,这也是它实现装饰链的基础,可以通过包装(decorating)对象来扩展其功能,同时保持对象接口不变,使用组合的方式,将装饰器对象嵌套在被装饰对象之中,形成一个装饰器链。装饰模式(半透明)类图:主要是在通过拓展具体装饰类来实现对象功能的扩展,而代理模式更倾向于用一个通用功能来给目标类做功能扩展,,举个反例:现在已有一个运用组合思想实现的静态代理类来给老功能做逻辑扩展,,后面发现新的需求需要新的扩展逻辑,,那我们就要再去重新写一个静态代理类,,然后后面发现新需求又来了,又要再重新添加扩展逻辑在写一个静态代理类,,该死的新需求老是需要新的扩展逻辑,这样导致我们针对同一个类写了好多代理类,发现这么多静态代理类特别难管理,没法对代码的规范方法命名什么做限制,很明显这种功能扩展的场景很不适合用静态代理模式,相反这种新需求累加的情况 非常适合用具有的组合性特点的装饰模式动态代理模式就更不用说了,两种动态代理模式(jdk动态代理基于字节码生成,通过在运行时动态创建一个实现代理接口的匿名类来实现代理与cglib动态代理通过生成目标类的子类来实现代理)本质都是运行时切面编程,在给一个固定的扩展逻辑动态创建更多的代理类来适配更多的目标类,只要你愿意的话,你可以将代理生成器中的目标类设置成Object

        其实代理模式只是不太适合给代码逻辑扩展比较频繁的场景做功能扩展,但是他又的确是代码功能扩展的一剂良药(基本没有什么前置设计限制,除了jdK动态代理的目标类有个必须是接口实现类的限制和cglib动态代理的目标类不可是final类的限制),装治疑难杂症(静态代理基本是想收拾谁收拾谁(当然最好是被代理类能实现一个接口或继承某个抽象类,这样更易于静态代理的逻辑复用,以及遵循依赖倒置原则),动态代理更是在rpc远程调用,延迟加载,日志记录,权限控制等等方面应用广泛),虽然会有些代价比如上面说代理类的增加,以及动态代理反射机制代理的性能开销

        上面我们主要讲了装饰模式与代理模式使用场景维度的区别,一个是装饰类强调的拓展逻辑的维度,另一个是代理类强调的逻辑复用的维度。

        接下来我们讲讲桥接模式将一个类的抽象部分与其实现部分分离,使它们可以独立地变化,简单讲就是设计之初就考虑到抽象类的非抽象方法的可变逻辑,将可变逻辑提取出来用接口属性中的方法去执行,这样就不需要通过不断的继承重写父类方法来实现逻辑拓展,注意这就是它本质解决的问题,两种桥接模式构造注入桥接模式set注入桥接模式构造注入桥接模式通过构造方法注入接口,单纯从调用者角度上看起来是否有点像继承的思想实现的静态代理,但其实正好相反,构造注入桥接模式是往目标类里构造注入接口实现对象,而继承的思想实现的静态代理是在代理类中通过构造被代理的父类对象并通过重写父类方法加扩展逻辑的方式在来实现对被代理父类对象的逻辑扩展,注意这里大家重点观察扩展逻辑写在哪,构造注入桥接模式自然是写在接口实现类中,而继承的思想实现的静态代理的扩展逻辑是写在代理类中啊,这样看来很明显对象桥接模式强调的是拓展逻辑的维度,同时应该注意构造注入桥接模式构造方法传递的只能是接口,而这种构造方式往往在抽象父类的构造方法中写死,而继承的思想实现的静态代理传递的是被代理对象构造方法需要的值甚至可以是无参构造(毕竟子类可以继承父类的所有方法可以很方便的通过重写来实现逻辑扩展),构造注入桥接模式其实就是通过构造注入的方式实现接口属性的注入,而set注入桥接模式采用set注入的方式实现接口属性的注入,这也是两种桥接模式的本质区别,但这并不影响set注入桥接模式在拓展逻辑上应用,反而使得代码变的更加灵活,构造注入只能在对象创建前注入,而set注入,可以在对象创建后注入,如果在只考虑单线程的情况下,我们可以用一个对象来应对各种扩展逻辑的变化,当然这不太符合单一职责原则,谨慎使用为妙!

        下面我们讲讲适配器模式本质,适配器解决是接口不兼容问题,将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

        适配器模式也分为类适配器模式(类适配器模式可以适配多个被适配者类,但是被适配者类的方法必须是可访问的,本质就是通过继承的方式实现;),对象适配器模式(对象适配器模式可以适配多个被适配者类,且被适配者类的方法可以是私有的,而且适配器类可以与被适配者类独立变化,本质就是通过组合的方式实现;),和接口适配器模式(接口适配器模式可以适配多个目标接口,因为适配器类是抽象类,可以定义多个抽象方法和默认实现),双向适配器模式(其实就是在适配器中组合双向适配的接口,然后在具体实现中完成方法调用的转换),单接口/缺省适配器模式(当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求。它适用于不想使用一个接口中的所有方法的情况)。,,没啥好讲的,适配器模式可能是结构型模式中最好理解的设计模式了。如过场景可以在组合和继承的实现方式中选择一种优先选组合方式来实现适配器-组合/聚合优先原则(注意这里的组合可不是组合模式)

        后面我们谈谈组合模式组合模式本质是将树形结构的一些需要递归遍历的操作通过结构的设计省去调用递归函数的逻辑,组合模式的关键是定义了一个抽象构件类,它既可以代表叶子,又可以代表容器。客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。同时容器对象与抽象构件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。

        组合模式又分透明组合模式如图(抽象构件中声明了所有用于管理成员对象的方法)

和安全组合模式如图

(抽象构件中只声明叶子节点和树枝节点的共有方法,因为叶子构件和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件类中定义,客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件)

一般情况下这里最佳的选择方案应该是在透明组合模式的基础上对叶子节点实现类的管理成员对象的方法做一些安全校验与异常处理与提示。

        再后面我们谈谈享元模式(定义:运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,是一种对象结构型模式。享元模式本质就是通过共享技术实现相同或相似对象的重用从而降低程序运行时对jvm内存的消耗,

实现享元模式关键在于区分内部状态外部状态,不同于桥接模式的抽象与实现的分离,享元模式通过将对象的内部状态共享在缓存中,外部状态由创建时或创建后指定

享元模式类图

  复合享元模式类图

       

         最后讲讲外观模式(外部与一个子系统的通信通过一个统一的外观角色进行,为子系统中的一组接口提供一个一致的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。)

在软件开发中,有时候为了完成一项较为复杂的功能,一个类需要和多个其他业务类交互,而这些需要交互的业务类经常会作为一个完整的整体出现,由于涉及的类比较多,导致使用时代码较为复杂。此时,特别需要一个类似服务员一样的角色,由它来负责和多个业务类进行交互,而使用这些业务类的类只需和该类交互即可。外观模式通过引入一个新的外观类来实现该功能。外观类多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互。

 

        

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

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

相关文章

JS逆向基础

JS逆向基础 一、什么是JS逆向?二、接口抓包三、逆向分析 一、什么是JS逆向? 我们在网站进行账号登录的时候对网页源进行抓包就会发现我们输入的密码在后台会显示为一串由字母或数字等符号,这就是经过加密呈现的一段加密文字,而分…

python脚本 链接到ssh服务器 快速登录ssh服务器 ssh登录

此文分享一个python脚本,用于管理和快速链接到ssh服务器。 效果演示 🔥完整演示效果 👇第一步,显然,我们需要选择功能 👇第二步,确认 or 选择ssh服务器,根据配置文件中提供的ssh信息,有以下情况 👇场景一,只有一个候选ssh服务器,则脚本会提示用户是否确认链…

blender径向渐变材质-着色编辑器

要点: 1、用纹理坐标中的物体输出连接映射中的矢量输入 2、物体选择一个空坐标,将空坐标延z轴上移一段距离 3、空坐标的大小要缩放到和要添加材质的物体大小保持一致

存 储 管 理

(1) 存储管理的任务和功能是什么? 解: 存储管理的主要任务是: 支持多道程序的并发执行,使多道程序能共享存储资源,在互不干扰的环境中并发执行。方便用户,使用户减少甚至摆脱对存储器的管理,使…

【前端】前后端通信方法与差异(未完待续)

系列文章 【Vue】vue增加导航标签 本文链接:https://blog.csdn.net/youcheng_ge/article/details/134965353 【Vue】Element开发笔记 本文链接:https://blog.csdn.net/youcheng_ge/article/details/133947977 【Vue】vue,在Windows IIS平台…

WPF中使用DataGrid封装组合控件TreeView+DataGrid

(关注博主后,在“粉丝专栏”,可免费阅读此文) wpf的功能非常强大,很多控件都是原生的,但是要使用TreeViewDataGrid的组合,就需要我们自己去封装实现。 我们需要的效果如图所示&#x…

Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580

Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 Apache ShenYu 网关JWT认证绕过漏洞 CVE-2021-37580 已亲自复现) 漏洞名称 漏洞描述 Apache ShenYu是一个异步的,高性能的&#x…

SpringBoot3-基础特性

文章目录 自定义 banner自定义 SpringApplicationFluentBuilder APIProfiles指定环境环境激活环境包含Profile 分组Profile 配置文件 外部化配置配置优先级 外部配置导入配置属性占位符 单元测试-JUnit5测试组件测试注解断言嵌套测试参数化测试 自定义 banner banner 就是启动…

机场信息集成系统系列介绍(7):机场航班信息显示系统FIDS

目录 一、简介 二、架构及相关功能 1、实时更新和显示航班信息 2、多屏显示与查询 3、提供登机口导航信息 4、发布机场公告 5、集成机场的其他延伸服务 6、支持多语言显示 7、监控与故障处理 8、数据分析与优化 9、与航空公司、地面代理的信息交互 10、安全保障与应…

【华为OD机试真题2023CD卷 JAVAJS】多段线数据压缩

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里 多段线数据压缩 知识点数组栈递归矩阵循环 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 下图中,每个方块代表一个像素,每个像素用其行号和列号表示。 为简化处理,多段线的走向只能是水平、竖直、斜向45…

GPT2代码运行,个人文本生成助手,不依赖OpenAI API调用

0.前言: 感觉GPT很好玩,所以想要有个自己搭建GPT的写法,不依赖于OpenAI,需要翻墙太麻烦了,近日日本已经结合GPT4和机器,可以让他吓人,做出丰富的表情,如果自己训练的话,会塑造出什么样的机器人尚未可知…抱着好奇的心态,去github openai下载了个gpt2的模型来玩玩(其中遇到了许多…

2016年第五届数学建模国际赛小美赛C题对超级细菌的战争解题全过程文档及程序

2016年第五届数学建模国际赛小美赛 C题 对超级细菌的战争 原题再现: 最近有很多关于我们抗生素耐药性危机的讨论。进化出的能够抵抗抗生素的细菌每年杀死70万人,越来越强大的细菌正在世界各地传播。研究人员担心,我们将进入一个后抗生素时代…

【Sass】网易云动画播放器

简介 仿网易云播放动画 效果图 sass src/assets/style/musicPlay.sass // TODO 音乐播放器动画 // ? 动画停止class >>> .muscic-play-stop // HTML结构 // <div class"music-play"> // <div class"bg-primary"></div>…

安捷伦Agilent 8720ES网络分析仪

Agilent安捷伦8720ES S-参数矢量网络分析仪 50MHz至20GHz 100 dB 的动态范围 优异的测量精度 2个测量通道 4个显示通道 频率和功率扫描 快扫描和数据传输速度 通过/失败测试&#xff0c;强大的标记功能 电校准&#xff08;ECal&#xff09; 内部使用测试序列的自动化 可选时域…

当物联网技术遇上圣诞节,会给你带来怎样的商业灵感

智能物联网项目可以将更浓烈的节日气氛融入到千家万户。有市场嗅觉的朋友已经踏上了这种创新与传统相遇的旅程&#xff0c;你可以参考一下他们的点子。 物联网智能照明 借助物联网技术&#xff0c;你可以创建一个智能照明系统&#xff0c;让每一束灯光闪烁出美妙的色彩或图案…

正则表达式与bs4选择器筛选论文数准确率之比较

一、正则爬取论文网首页论文标题的示例 import requests import re from bs4 import BeautifulSoupheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36}def get_html(url):try:res…

4种常见的数据库索引

数据库索引是优化数据库系统性能的关键组成部分。如果没有有效的索引&#xff0c;查询可能会变得缓慢且低效&#xff0c;从而导致用户体验不佳并降低生产力。在这篇文章中&#xff0c;我们将探讨创建和使用数据库索引的一些最佳实践。 常见的索引算法有&#xff1a; 1. B-Tree…

Hadoop入门学习笔记——二、在虚拟机里部署HDFS集群

视频课程地址&#xff1a;https://www.bilibili.com/video/BV1WY4y197g7 课程资料链接&#xff1a;https://pan.baidu.com/s/15KpnWeKpvExpKmOC8xjmtQ?pwd5ay8 Hadoop入门学习笔记&#xff08;汇总&#xff09; 目录 二、在虚拟机里部署HDFS集群2.1. 部署node1虚拟机2.2. 部…

【Angular】Angular中的最差实践

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

【数据结构入门精讲 | 第十六篇】并查集知识点及考研408、企业面试练习

上一篇中我们进行了散列表的相关练习&#xff0c;在这一篇中我们要学习的是并查集。 目录 概念伪代码选择题填空题编程题7-1 朋友圈R7-1 笛卡尔树R7-2 部落R7-3 秀恩爱分得快 在许多实际应用场景中&#xff0c;我们需要对元素进行分组&#xff0c;并且在这些分组中进行查询和修…