JAVA设计模式结构型模式

一、前言

java设计模式主要分为创建型模式,结构型模式和行为型模式。上一篇主要总结了行为型设计模式,本章总结,结构型模式。像创建型模式就不写了,比较简单。大概知道是工厂模式和建造者模式,原型模式就行,大家都懂,项目中运用非常广泛。本节只总结结构型模式。

二、java设计模式结构型模式(主要摘自知乎朱鸭鸭的博文)

结构模型:适配器模型、桥接模型、过滤器模型、组合模型、装饰器模型、外观模型、享受元模型和代理模型。

1、适配器模式

问题

当你有两个不兼容的接口(即类或对象),但需要它们能够一起工作时,适配器模式可以解决这个问题。例如,你可能有一个已存在的类库或组件,但其接口与你的代码不匹配,你希望能够无缝地将它们集成在一起。

解决方案

适配器模式通过引入一个适配器类来充当中间人,将一个接口转换成另一个接口,使得两个不兼容的对象能够协同工作。适配器类包含一个对不兼容接口的引用,并实现了你期望的目标接口。这样,当你需要使用目标接口的时候,可以通过适配器来调用原本不兼容的类的方法。

效果

适配器模式的应用可以使得现有的代码与新代码能够无缝协同工作,从而提高了代码的可重用性。它允许你将不同系统、库或组件整合在一起,而无需对现有代码进行大量修改。然而,适配器模式也可能引入一些复杂性,因为你需要维护适配器类和处理不同接口之间的映射关系。

总的来说,适配器模式是一种很有用的模式,特别适合在集成不同组件或类时,解决接口不匹配的问题,从而保持代码的灵活性和可维护性。

总结:一句话就是对内封装,对外提供接口。

2、桥接模式

问题

在软件设计中,有时候你会遇到一个类有多个变化维度(例如抽象和具体的实现)。如果使用继承来处理这些变化,将会导致类层次结构的急剧增加,难以管理和维护。此外,继承会将抽象部分和具体部分紧密耦合,不利于独立地进行扩展和变化。

解决方案

桥接模式通过将抽象部分和具体部分分离,使它们可以独立地变化。在桥接模式中,通过创建一个桥接接口(或抽象类),其中包含一个指向具体实现的引用,将抽象部分和具体部分连接起来。这样,抽象部分和具体部分可以独立地进行扩展,而不会相互影响。这种方式也被称为“组合优于继承”。

效果

桥接模式的应用能够提供更好的灵活性和可扩展性。它允许抽象部分和具体部分独立变化,避免了类层次结构的爆炸式增长。这样可以更容易地添加新的抽象部分和具体部分,而不会影响到彼此。然而,使用桥接模式可能会引入一些复杂性,因为你需要管理更多的类和对象。

总之,桥接模式是一种有助于解耦抽象和实现,提供更灵活、可扩展设计的设计模式。它适用于那些需要处理多个变化维度的情况,同时又希望保持代码的清晰结构和可维护性。

总结一句话:其实就是将抽象和具体进行分离,才有组合模式,扩展类功能。

3、过滤器模式

过滤器模式(Filter Pattern)又称标准模式(Criteria Pattern)是一种设计模式,属于结构型模式。这种模式允许开发人员使用不同的标准来过滤一组对象,通过运算逻辑以解耦的方式将它们连接起来。过滤器模式可结合多个标准来获得单一标准。说白了,就是按条件筛选一组对象出来。

过滤器模式的实现
过滤器模式角色
抽象过滤器角色(AbstractFilter):负责定义过滤器的实现接口,具体的实现还要具体过滤器角色去参与,客户端可以调用抽象过滤器角色中定义好的方法,将客户端的所有请求委派到具体的实现类去,从而让实现类去处理;
具体过滤器角色(ConcreteFilter):该角色负责具体筛选规则的逻辑实现,最后再返回一个过滤后的数据集合,标准的过滤器只对数据做过滤,当然也可以对集合中的数据做某项处理,再将处理后的集合返回;
被过滤的主体角色(Subject):一个软件系统中可以有一个或多个目标角色,在具体过滤器角色中会对指定感兴趣的目标进行处理,以确保后面的数据确实是我想要的。 文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

                        

4、组合模式

问题:

在某些情况下,我们需要处理一组对象,这些对象之间具有整体-部分的关系。我们希望能够以一致的方式处理单个对象和对象组合,而不需要对它们进行特殊处理。

解决方案:

组合模式的解决方案是将对象组合成树状结构,其中树的节点可以是单个对象或对象组合。这样,无论是操作单个对象还是对象组合,都可以使用统一的方式进行操作。组合模式通过定义一个共同的抽象类或接口来表示单个对象和对象组合,从而实现了透明的处理。

在组合模式中,通常有两种主要角色:

  1. 组件(Component): 这是一个抽象类或接口,定义了单个对象和对象组合共同的操作。它可以有一些默认实现,也可以有抽象方法需要在具体子类中实现。
  2. 叶子(Leaf): 继承自组件,表示单个对象。它没有子对象。
  3. 复合(Composite): 继承自组件,表示对象组合。它包含了一组子对象,这些子对象可以是叶子,也可以是复合。

5.装饰模式

问题

在某些情况下,我们需要在不修改现有对象结构的情况下,动态地添加功能或责任。继承在这种情况下可能会导致类爆炸问题,而且修改现有类可能会影响到其他部分的代码。

解决方案

装饰模式提供了一种在运行时动态地为对象添加新功能的方法,通过创建一个装饰类来包装原始类。装饰类具有与原始类相同的接口,它内部包含一个指向原始对象的引用,并且可以根据需要包装额外的功能。这样,你可以通过组合不同的装饰类来构建出具有不同功能组合的对象。

效果

装饰模式的优点包括避免了类爆炸问题,因为你可以通过组合少量的装饰类来实现各种功能组合。它也使得功能的增加和修改更加灵活,不会影响到其他部分的代码。然而,装饰模式可能会导致增加很多小型的类,从而增加了代码的复杂性。

在装饰模式中,通常涉及以下角色:

  1. 组件(Component):定义了一个抽象的接口,可以是具体对象或装饰器所共有的接口。
  2. 具体组件(Concrete Component):实现了组件接口,是被装饰的原始对象。
  3. 装饰器(Decorator):持有一个指向组件对象的引用,并实现了组件的接口。它可以包含额外的功能,也可以将请求传递给组件对象。
  4. 具体装饰器(Concrete Decorator):扩展了装饰器类,通过添加额外的功能来装饰具体组件。

6、外观模式

问题

在软件开发中,系统可能变得非常复杂,包含多个子系统和各种交互。这些子系统之间的依赖关系和调用可能变得混乱,导致系统难以理解、扩展和维护。在这种情况下,我们需要一种方法来提供一个简单的接口,将复杂的子系统调用和依赖关系进行封装,使客户端能够更轻松地与系统进行交互。

解决方案

外观模式通过引入一个外观类(Facade),将复杂的子系统接口进行封装,为客户端提供一个简单的高层接口。外观类充当了客户端与子系统之间的中间人,处理客户端的请求并将其转发给适当的子系统。外观模式并不在系统中添加新功能,它只是提供了一个更简洁的接口,以简化客户端的操作。

效果

外观模式的应用可以带来以下效果:

    • 简化接口:客户端只需要与外观类交互,无需了解底层子系统的复杂性。
    • 降低耦合:外观模式将客户端与子系统解耦,使得系统的变化不会影响客户端代码。
    • 提高可维护性:由于外观模式将子系统封装起来,修改子系统的实现不会影响客户端代码,从而提高了系统的可维护性。
    • 支持松散耦合:外观模式可以帮助系统中的不同模块之间实现松散耦合,从而支持模块的独立开发和测试。

总之,外观模式通过提供一个简化的接口,将复杂的子系统封装起来,帮助提高系统的可用性、可维护性和灵活性。它在处理复杂系统的同时,使客户端代码更加清晰和易于理解。

7、享元模式

问题

在某些情况下,一个应用程序可能需要大量相似对象,而这些对象的大部分属性是相同的。在这种情况下,创建大量相似对象会占用大量的内存和系统资源,导致系统性能下降。

解决方案

享元模式的解决方案是共享对象的状态,以减少内存和资源的消耗。它将对象分为两部分:内部状态(Intrinsic State)和外部状态(Extrinsic State)。内部状态是对象共享的部分,而外部状态是每个对象特有的部分。

享元模式通过一个享元工厂(Flyweight Factory)来管理和创建共享对象。当需要一个对象时,工厂会检查是否已经有相同内部状态的对象存在,如果存在则返回已有的对象,否则创建一个新的对象并将其添加到内部对象池中。

效果

  • 优点:享元模式可以显著减少内存消耗,因为共享对象的内部状态只有一份。这可以在需要大量相似对象的情况下节省内存。同时,由于共享对象已经存在于池中,创建时间和性能开销也会降低。
  • 权衡:享元模式引入了内部状态和外部状态的区分,这可能增加了系统的复杂性。此外,对内部状态的共享需要考虑线程安全性。
  • 限制:享元模式适用于对象的内部状态相对稳定,而外部状态会变化的情况。如果一个对象的状态完全相同,那么不需要使用享元模式。
  • 可能的后果:通过减少对象的创建和内存占用,系统性能可能会得到提升。但在一些情况下,过度使用享元模式可能会引入不必要的复杂性,因此需要根据具体情况进行权衡。

享元模式在需要大量相似对象的场景中非常有用,例如文字处理软件中的字符对象、图像处理软件中的像素对象等。它可以显著提高系统的性能和资源利用率。

8、代理模式

问题:

在某些情况下,我们希望通过一个中间代理来控制对某个对象的访问。这可能是因为原始对象的创建或访问涉及复杂的逻辑,或者我们想要在访问原始对象之前或之后执行一些操作。

解决方案:

代理模式提供了一个代理对象,它充当了原始对象的替代品,以控制对原始对象的访问。代理对象与原始对象实现相同的接口,使得客户端可以无缝地切换和使用。代理对象可以对客户端的请求进行拦截、修改或增强,然后将请求传递给原始对象。

效果:

代理模式的应用可以带来多种效果:

  • 远程代理(Remote Proxy): 代理对象可以隐藏原始对象存在于远程服务器上的事实,使得客户端可以透明地访问远程对象。这对于分布式系统非常有用。
  • 虚拟代理(Virtual Proxy): 当创建原始对象需要大量资源时,代理对象可以充当一个轻量级的替代品,延迟原始对象的实际创建和初始化,从而提高性能。
  • 保护代理(Protection Proxy): 代理对象可以控制对原始对象的访问权限,确保只有具有特定权限的客户端可以访问原始对象。
  • 缓存代理(Cache Proxy): 代理对象可以缓存原始对象的结果,以便在后续相同请求时能够直接返回缓存的结果,减少重复计算。
  • 日志记录代理(Logging Proxy): 代理对象可以在访问原始对象之前或之后记录日志,用于调试、监控或审计。

总之,代理模式允许我们在不改变原始对象的情况下,通过引入代理对象来添加额外的控制和功能。这有助于提高代码的可维护性、可扩展性和灵活性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Atcoder ABC340 E - Mancala 2

Mancala 2(曼卡拉 2) 时间限制:2s 内存限制:1024MB 【原题地址】 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【样例输入1】 …

主流开发语言和开发环境介绍

主流开发语言和开发环境介绍文章目录 ⭐️ 主流开发语言:2024年2月编程语言排行榜(TIOBE前十)⭐️ 主流开发语言开发环境介绍1.Python2.C3.C4.Java5.C#6.JavaScript7.SQL8.GO9.Visual Basic10.PHP ⭐️ 主流开发语言:2024年2月编程…

2024年2月的TIOBE指数,go语言排名第8,JAVA趋势下降

二月头条:go语言进入前十 本月,go在TIOBE指数前10名中排名第8。这是go有史以来的最高位置。当谷歌于2009年11月推出Go时,它一炮而红。在那些日子里,谷歌所做的一切都是神奇的。在Go出现的几年前,谷歌发布了GMail、谷歌…

SpringBoot+WebSocket实现即时通讯(二)

前言 紧接着上文《SpringBootWebSocket实现即时通讯(一)》 本博客姊妹篇 SpringBootWebSocket实现即时通讯(一)SpringBootWebSocket实现即时通讯(二)SpringBootWebSocket实现即时通讯(三&…

NestJS入门8:拦截器

前文参考: NestJS入门1:创建项目 NestJS入门2:创建模块 NestJS入门3:不同请求方式前后端写法 NestJS入门4:MySQL typeorm 增删改查 NestJS入门5:加入Swagger NestJS入门6:日志中间件 Nes…

LeetCode 0105.从前序与中序遍历序列构造二叉树:分治(递归)——五彩斑斓的题解(若不是彩色的可以点击原文链接查看)

【LetMeFly】105.从前序与中序遍历序列构造二叉树:分治(递归)——五彩斑斓的题解(若不是彩色的可以点击原文链接查看) 力扣题目链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-a…

小清新卡通人物404错误页面源码

小清新卡通人物404错误页面源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面,重定向这个界面 蓝奏云:https://wfr.lanzout.com/i6XbU1olftde

区块链游戏解说:什么是 Nine Chronicles

作者:lesleyfootprint.network 编译:cicifootprint.network 数据源: Nine Chronicles Dashboard 什么是 Nine Chronicles Nine Chronicles 是一款去中心化的在线角色扮演游戏,标志着在线游戏和区块链技术的发展。 Nine Chroni…

ubuntu分辨率更改、开机被重置、ubuntu屏幕小

ubuntu分辨率更改 分辨率改成:1920x1200 xrandr --size 1920x1200 在此之前可以先输入 xrandr 看支持哪些分辨率 开机被重置 我已经设置成这样了, 一开机变回这个 ubuntu屏幕小 输入命令行 xrandr --size 1920x1200 这个下次重启ubuntu又会重置…

C++(18)——适配器概念以及stack、queue、优先队列的模拟实现

上篇文章中,给出了对于模拟实现中功能的补全,本篇文章将优先介绍一个新的容器之后引入什么是适配器,以及适配器的使用方法,再通过适配器的思想来完成对于,、优先级队列_的实现。 目录 1. deque: 1.1 什么是deque&…

ASP.NET-实现图形验证码

ASP.NET 实现图形验证码能够增强网站安全性,防止机器人攻击。通过生成随机验证码并将其绘制成图像,用户在输入验证码时增加了人机交互的难度。本文介绍了如何使用 C# 和 ASP.NET 创建一个简单而有效的图形验证码系统,包括生成随机验证码、绘制…

树莓派4B傻瓜式安装系统配置(无显示器)

一、前言: 本教程详细描述树莓派如何装系统,如何连接电脑显示屏,有详细安装包,有需要的可以点击链接下载,没有会员的宝宝可以关注后私信我。 (树莓派4B傻瓜式安装系统配置(无显示器&#xff0…

onlyoffice基础环境搭建+部署+demo可直接运行 最简单的入门

office这个体系分为四个大教程 1、【document server文档服务器基础搭建】 2、【连接器(connector)或者jsApi调用操作office】-进阶 3、【document builder文档构造器使用】-进阶 4、【Conversion API(文档转化服务)】-进阶 如果需要连接器,可以查看:onl…

Fiddler如何比较两个接口请求?

进行APP测试时,往往会出现Android和iOS端同一请求,但执行结果不同,这通常是接口请求内容差异所致。 我习惯于用Fiddler抓包,那此时应该如何定位问题呢? 分别把Android和iOS的接口请求另存为TXT文件,然后用…

leetcode hot100零钱兑换Ⅱ

本题可以看出也是背包问题,但区别于之前的01背包问题,这个是完全背包问题的变形形式。 下面介绍01背包和完全背包的区别与联系: 01背包是背包中的物品只能用一次,不可以重复使用,而完全背包则是可以重复使用。01/完全…

体验一下UE5.3的Skeletal Editor

UE5.3中增加了蒙皮网格骨架编辑工具,用户无需导出Fbx就可以直接编辑蒙皮网格,支持修改绑定姿势的骨骼位置、修改蒙皮权重、对已蒙皮多边形进行编辑以及对蒙皮网格减免等操作,就来体验一下。 1.加载插件 要使用Skeletal Editor功能&#xff…

使用系统调用实现shell命令之【ls -l】

时间获取: 1.time time_t time(time_t *tloc); 功能: 返回1970-1-1到现在的秒数(格林威治时间) 参数: tloc:存放秒数空间首地址 返回值: 成功返回秒数 失败返回-1 2.localtime stru…

Stable Diffusion——基础模型、VAE、LORA、Embedding各个模型的介绍与使用方法

前言 Stable Diffusion(稳定扩散)是一种生成模型,基于扩散过程来生成高质量的图像。它通过一个渐进过程,从一个简单的噪声开始,逐步转变成目标图像,生成高保真度的图像。这个模型的基础版本是基于扩散过程…

ESMFold conda安装、使用及与AlphaFold的简单比较

文章目录 前言一、ESMFold是什么?二、安装步骤1. 确认安装环境:cuda toolkit版本2. 创建ESMFold conda环境并安装Step 1:创建conda环境,下载需要的包Step 2:激活conda环境,继续pip安装 3. 运行结构预测 三、…

pom.xml常见依赖及其作用

1.org.mybatis.spring.boot下的mybatis-spring-boot-starter:这个依赖是mybatis和springboot的集成库,简化了springboot项目中使用mybatis进行持久化操作的配置和管理 2.org.projectlombok下的lombok:常用注解Data、NoArgsConstructor、AllA…