当前位置: 首页 > news >正文

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): 代理对象可以在访问原始对象之前或之后记录日志,用于调试、监控或审计。

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

相关文章:

JAVA设计模式结构型模式

一、前言 java设计模式主要分为创建型模式,结构型模式和行为型模式。上一篇主要总结了行为型设计模式,本章总结,结构型模式。像创建型模式就不写了,比较简单。大概知道是工厂模式和建造者模式,原型模式就行&#xff0…...

第4讲引入JWT前后端交互

引入JWT前后端交互 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519); JWT就是一段字符串,用来进行用户身份认证的凭证,该字符串分成三段【头部、载荷、签证】 后端接口测试&…...

基于Java的车辆租赁管理平台/租车系统

功能介绍 平台采用B/S结构,后端采用主流的Springboot框架进行开发,前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 前台功能包括:首页、车辆详情、车辆预订、用户中心模块。后台功能包括:车辆管理、分类管理…...

如何升级至ChatGPT Plus:快速指南,ChatGPT的秘密武器GPT4.0是什么?

提到 ChatGPT。想必大家都有所耳闻。自从 2022 年上线以来,就受到国内外狂热的追捧和青睐,上线2个月,月活突破1个亿!!! 而且还在持续上涨中。因为有很多人都在使用 ChatGPT 。无论是各大头条、抖音等 App、…...

【天衍系列 05】Flink集成KafkaSink组件:实现流式数据的可靠传输 高效协同

文章目录 01 KafkaSink 版本&导言02 KafkaSink 基本概念03 KafkaSink 工作原理1.初始化连接2.定义序列化模式3.创建KafkaSink算子4.创建数据源5.将数据流添加到KafkaSink6.内部工作机制 04 KafkaSink参数配置05 KafkaSink 应用依赖06 KafkaSink 快速入门6.1 包结构6.2 项目…...

深度学习之pytorch实现逻辑斯蒂回归

深度学习之pytorch实现逻辑斯蒂回归 解决的问题数学公式logiatic函数损失值 代码与线性回归代码的区别数据损失值构造回归的函数 结果分析 解决的问题 logistic 适用于分类问题,这里案例( y为0和1 ,0和 1 分别代表一类) 于解决二分类&#xf…...

有事休假店铺无人看守怎么办?智能远程视频监控系统保卫店铺安全

在春节期间,很多自营店主也得到了久违的假期,虽然很多店主都是长期在店铺中看守,但遇到春节这样的日子,多数人还是选择回乡休假。面对店主休假或有事不能管理店铺时,传统的监控虽然可以做到单一的监控,却仍…...

酷开科技 | 酷开系统壁纸模式,让过年更有氛围感!

在阵阵爆竹声中,家家户户都沉浸在浓浓的年味中。过年,是团圆,是温暖。团团圆圆的日子里,仪式感不可少,换上一张喜气洋洋的电视壁纸吧,寓意幸福一年又一年。打开酷开系统壁纸模式挑选一张年味十足的壁纸&…...

Docker中部署flink集群的两种方式

文章目录 一、概述二、准备工作三、方式一四、方式二1、准备配置文件2、执行 docker 命令 一、概述 本文将通过 2 种方式在 docker 中部署 flink standalone 集群,集群中共有 4 个节点,分别是 1 个 jobManager 节点和 3 个 taskManager 节点。方式一能快…...

八、计算机视觉-边界填充

文章目录 前言一、原理二、具体的实现 前言 在Python中使用OpenCV进行边界填充(也称为zero padding)是一种常见的图像处理操作,通常用于在图像周围添加额外的像素以便进行卷积或其他操作。下面是使用OpenCV进行边界填充的基本原理和方法 一…...

ffmpeg 硬件加速介绍

基于OS的硬件加速 Windows 参考[2],基于windows的硬件加速都是基于DirectX API,我们可以用ffmpeg -hwaccels查看当前环境支持的硬件加速接口,如下为windows上的执行ffmpeg --hwaccels的结果。 在linux上执行ffmpeg -hwaccels的结果如下: 可以看到windows上支持的硬件加速…...

【QT+QGIS跨平台编译】之三十九:【Exiv2+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、Exiv2介绍二、文件下载三、文件分析四、pro文件4.1 exiv2-xmp4.2 exiv2lib_int4.3 exiv2lib五、编译实践一、Exiv2介绍 Exiv2是一个开源的C++库,用于读取、编辑和写入图片和视频文件的元数据。它可以处理各种类型的元数据,包括EXIF、IPTC、XMP等。 元数据是与…...

术业有专攻!三防加固平板助力工业起飞

在日常使用中的商业电脑比较追求时效性,以市场定位做标准,内部元件只需满足一般要求就行,使用寿命比较短。而三防平板电脑是主要运用在复杂、恶劣的环境下所以在需求方面较高,需要保证产品在恶劣条件下正常使用,满足行业领域的需求…...

适合tiktok运营的云手机需要满足什么条件?

TikTok作为一款全球热门的社交媒体平台,具有无限的市场潜力。然而,卖家在运营过程中常常会面临到视频0播、账号被降权、限流等问题,甚至可能因为多人同时使用一个IP而导致封号的风险。为了规避这些问题,越来越多的卖家将目光投向了…...

微服务-微服务Nacos配置中心

1.1 配置中心架构 1.2 Config Client源码分析 配置中心核心接口ConfigService public class ConfigServerDemo {public static void main(String[] args) throws NacosException, InterruptedException {String serverAddr "localhost";String dataId "naco…...

配置Python环境及job运行的虚拟环境

1、配置Jenkins的Python环境:Manage Jnekins-Global Tool Configuration-Python 2、安装pyenv插件 此插件会给每个job都创建一个虚拟Python环境 安装后,在job config-build中选择 virtualenv builder build job的时候会自动在/opt/jenkins(node主机的…...

【Java】图解 JVM 垃圾回收(二):垃圾收集器、Full GC

图解 JVM 垃圾回收(二) 1.垃圾收集器1.1 内存分配与回收策略1.2 Serial 收集器1.3 Parallel Scavenge 收集器1.4 ParNew 收集器1.5 CMS 收集器1.6 G1 收集器 2.Full GC 的触发条件 1.垃圾收集器 Java 虚拟机提供了多种垃圾回收器,每种回收器…...

Opencv绘图之rectangle、circle、line、ellipse、Rect、RotatedRect、Point

OpenCV中提供了多种函数来在图像上绘制各种基本形状,如矩形、圆形、线条、椭圆等。同时,Rect和RotatedRect是用来表示矩形区域的类,它们在图像处理中非常有用,尤其是在需要定义和操作图像区域时。Point类用于表示二维空间中的一个…...

HTML 字符实体参考清单

前言 一些字符在 HTML 中是预留的&#xff0c;拥有特殊的含义&#xff0c;比如小于号‘<’用于定义 HTML 标签的开始。如果我们希望浏览器正确地显示这些字符&#xff0c;我们必须在 HTML 源码中插入字符实体。 字符实体有三部分&#xff1a;一个和号‘&’和一个实体名…...

设计模式二:代理模式

1、什么是动态代理 可能很多小伙伴首次接触动态代理这个名词的时候&#xff0c;或者是在面试过程中被问到动态代理的时候&#xff0c;不能很好的描述出来&#xff0c;动态代理到底是个什么高大上的技术。不方&#xff0c;其实动态代理的使用非常广泛&#xff0c;例如我们平常使…...

php使用get_browser()函数将移动端和pc端分开

首先&#xff0c;确保你的PHP版本支持get_browser函数。get_browser函数是PHP内置的函数&#xff0c;但需要配置php.ini文件中的browscap参数&#xff0c;指定一个浏览器配置文件。 下载浏览器配置文件。你可以从 https://download.csdn.net/download/bigorange1/88850695 下…...

更改WordPress作者存档链接author和Slug插件Edit Author Slug

WordPress默认所有用户的存档永久链接都是/author/username/&#xff0c;不管是管理员还是订阅者或贡献者或作者或编辑。如果你想要自定义用户存档链接&#xff0c;比如根据角色不同使用不一样的author&#xff0c;或者自定义作者链接中的用户名Slug&#xff0c;那么建议考虑使…...

RISCV——Spinlock锁的理解

目录 1. 原子操作 2. 锁是干嘛的 3. 锁的实现 1. 原子操作 gcc从4.1.2开始提供了__sync_*系列的build-in函数&#xff0c;用于提供加减和逻辑运算的原子操作&#xff0c;主要接口的其声明如下&#xff1a; type __sync_fetch_and_add (type *ptr, type value, ...): 将valu…...

阿里云幻兽帕鲁Windows 服务器怎么下载存档?

阿里云幻兽帕鲁Windows 服务器怎么下载存档&#xff1f;通过远程连接window服务器桌面的方式。 远程连接到阿里云的 Windows 服务器后&#xff0c;可以将压缩后的存档文件&#xff0c;拖动到 workbench\Download 目录后&#xff0c;就会触发浏览器的文件下载&#xff0c;然后将…...

ArcGIS API for JavaScript 4.X 本地部署(js,字体)

0 目录&#xff08;4.19&#xff09; /4.19/ 1 修改文件 1.1 init.js 编辑器打开/4.19/init.js搜索文本[HOSTNAME_AND_PATH_TO_JSAPI]&#xff0c;然后将其连同前面的https://替换为http://ip地址/4.19&#xff0c;可以是localhost&#xff0c;只能本机引用 替换后&#xff…...

202427读书笔记|《猫的自信:治愈系生活哲学绘本》——吸猫指南书,感受猫咪的柔软慵懒与治愈

202427读书笔记|《猫的自信&#xff1a;治愈系生活哲学绘本》——吸猫指南书&#xff0c;感受猫咪的柔软慵懒与治愈 《猫的自信&#xff1a;治愈系生活哲学绘本》作者林行瑞&#xff0c;治愈系小漫画绘本&#xff0c;10分钟可以读完的一本书&#xff0c;线条明媚&#xff0c;自…...

数据结构链表力扣例题AC(2)——代码以及思路记录

206. 反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 AC方法1 struct ListNode* reverseList(struct ListNode* head) {if(head NULL)return NULL;struct ListNode* n1, *n2, *n3;n1 NULL;n2 head;n3 head->next;while…...

C++面试宝典第30题:分发饼干

题目 假设你是一位非常棒的家长,想要给你的孩子们分发一些小饼干。但是,每个孩子最多只能给一块饼干。对每一个孩子i,都有一个胃口值gi,这是能让孩子们满足胃口的饼干的最小尺寸。对每一块饼干j,都有一个尺寸sj。如果sj >= gi,我们就可以将这个饼干j分配给孩子i,这个…...

文件包含+文件上传漏洞(图片马绕过)

目录 一.文件包含二.文件上传三.图片马四.题目 一.文件包含 将已有的代码以文件形式包含到某个指定的代码中&#xff0c;从而使用其中的代码或者数据&#xff0c;一般是为了方便直接调用所需文件&#xff0c;文件包含的存在使得开发变得更加灵活和方便&#xff08;若对用户输入…...

华为配置旁挂二层组网隧道转发示例

配置旁挂二层组网隧道转发示例 组网图形 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件扩展阅读 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响用户的业务使用。 组网需求 AC组…...