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

news2025/1/20 1:39:00

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

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

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

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

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

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

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

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

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

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

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

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

和安全组合模式如图

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

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

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

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

享元模式类图

  复合享元模式类图

       

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

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

 

        

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

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

相关文章

二叉搜索树 --- C++实现

目录 1.二叉搜索树的概念 2.二叉搜索树的操作 3. 二叉树的实现 4.二叉搜索树的应用 5. 二叉树的性能分析 6. 二叉树进阶练习题 1.二叉搜索树的概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左…

双非本科求职_面试经验_上集

前言 后知后觉开始找实习,也马上进入秋招,写此文一方面是记录一下我的面试经历作为复盘,另一方面也给同样在广州,双非二本的同志一个参考(快来看菜鸟),从而获得一定的动力和自信,毕…

【水文专业词汇】气象水文、水利工程等

水文专业词汇:气象水文、水利工程等 气象水文类水循环过程地区分类 水利工程类跨流域调水工程 参考 气象水文类 水循环过程 中文英文降水/降雨precipitation/rainfall径流runoff/streamflow产汇流runoff generation 地区分类 中文英文雨养作物区rain-fed agricu…

多模态大模型:关于Better Captions那些事儿

Overview 一、ShareGPT4V1.1、Motivation1.2、ShareGPT4V数据集构建1.3、ShareGPT4V-7B模型 一、ShareGPT4V 题目: ShareGPT4V: Improving Large Multi-Modal Models with Better Captions 机构:中科大,上海人工智能实验室 论文: https://arxiv.org/pdf…

少儿编程:从兴趣到升学的关键之路

随着科技的飞速发展,计算机编程已经逐渐渗透到我们生活的方方面面。对于新时代的少儿来说,掌握编程技能不仅可以开拓视野,提高思维能力,还可能成为他们未来升学和就业的重要砝码。6547网将探讨如何将少儿编程从兴趣培养成一种有力…

基于ERC20代币协议实现的去中心化应用平台

文章目录 内容简介设计逻辑ERC20TokenLoanPlatform 合约事件结构体状态变量函数 Remix 运行实现部署相关智能合约存款和取款贷款和还款 源码地址 内容简介 使用 solidity 实现的基于 ERC20 代币协议的借贷款去中心化应用平台(极简版)。实现存款、取款、贷款、还款以及利息计算的…

低代码开发:数字化转型的引擎

引言 在当今数字化时代,组织面临着不断变化的市场需求和技术挑战。数字化转型已成为维持竞争力的关键,而低代码开发正在崭露头角,成为加速创新和数字化转型的有力工具。本文将深入探讨低代码开发的核心概念、优势和应用,以揭示它…

单调栈分类、封装和总结

作者推荐 map|动态规划|单调栈|LeetCode975:奇偶跳 通过枚举最小(最大)值不重复、不遗漏枚举所有子数组 C算法:美丽塔O(n)解法单调栈左右寻找第一个小于maxHeight[i]的left,right,[left,right]直接的高度都是maxHeight[i] 可以…

【动态规划算法(dp算法)】之背包问题

文章目录 背包问题动规五部曲一、0-1背包问题 :限制物品不可重复 (要么不选 要么选一个)二、完全背包问题:不限制重复(要么不选 要么可以多选)(完全背包可以转化为0-1背包问题) 动态规划:01背包…

宝塔面板 -- 创建第一个自己的网站

文章目录 前言 一、安装宝塔面板 二、注册宝塔面板 三、安装nginx 四、第一个hello world运行 五、总结 文章目录 前言一、安装宝塔面板二、注册宝塔面板三、安装nginx四、第一个hello world运行五、总结 前言 阿里云最近对在校大学生免费每人赠送一台服务器&#xff0c…

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

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

第九周算法题(哈希映射,二分,Floyd算法 (含详细讲解) )

第九周算法题 第一题 题目来源&#xff1a;33. 搜索旋转排序数组 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a;整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 <…

HA启动Advanced SSH Web Terminal 提示附加组件似乎尚未准备就绪,它可能仍在启动。是否要再试一次?

环境&#xff1a; Home Assistant OS11.1 Advanced SSH & Web Terminal 17.0 问题描述&#xff1a; HA安装好SSH加载项&#xff0c;启动Advanced SSH & Web Terminal 提示附加组件似乎尚未准备就绪&#xff0c;它可能仍在启动。是否要再试一次&#xff1f; 解决方案…

尚硅谷 java 2023(基础语法)笔记

一、变量与运算符 1、HelloWorld的编写和执行 class HelloChina{public static void main(String[] args){System.out.println("hello,world!!你好&#xff0c;中国&#xff01;");} } 总结&#xff1a; 1. Java程序编写和执行的过程&#xff1a; 步骤1&#xff1…

解决 MATLAB 遗传算法中 exitflg=4 的问题

一、优化问题简介 以求解下述优化问题为例&#xff1a; P 1 : min ⁡ p ∑ k 1 K p k s . t . { ∑ k 1 K R k r e q l o g ( 1 α k ∗ p k ) ≤ B b s , ∀ k ∈ K p k ≥ 0 , ∀ k ∈ K \begin{align} {P_1:}&\mathop{\min}_{\bm{p}}{ \sum\limits_{k1}^K p_k } \no…

微软写了份GPT-4V说明书:166页讲解又全又详细demo示例一应俱全

原文&#xff1a;微软写了份GPT-4V说明书&#xff1a;166页讲解又全又详细demo示例一应俱全 - 哔哩哔哩 编者按&#xff1a;这篇文章深入研究了GPT-4V的用法、基本功能&#xff0c;用较大篇幅介绍了GPT-4V在遵循文字说明、视觉指向和视觉参考提示、视觉文本提示等方面展示出的…

Swiper轮播图系列

一、初始化Swiper new Swiper(.swiper-container, {initialSlide: 0,slidesPerView: 3,breakpoints: {750: {slidesPerView: 1},990: {slidesPerView: 2}},spaceBetween: 12,loop: true,speed: 1000,autoplay: {disableOnInteraction: false, // 手动滑动后&#xff0c;不停止…

阿里云 ACK One 新特性:多集群网关,帮您快速构建同城容灾系统

云布道师 近日&#xff0c;阿里云分布式云容器平台 ACK One[1]发布“多集群网关”[2]&#xff08;ACK One Multi-cluster Gateways&#xff09;新特性&#xff0c;这是 ACK One 面向多云、多集群场景提供的云原生网关&#xff0c;用于对多集群南北向流量进行统一管理。 基于 …

【UML】第9篇 类图(概念、作用和抽象类)(1/3)

目录 一、类图的概念 二、类图的主要作用 三、类图的构成 3.1 类的名称 3.2 抽象类&#xff08;Abstract Class&#xff09; 一、类图的概念 类图是UML模型中静态视图。它用来描述系统中的有意义的概念&#xff0c;包括具体的概念、抽象的概念、实现方面的概念等。静态视…

Pytorch项目,肺癌检测项目之四

# 安装图像处理 的两个包 simpleITK 和 ipyvolume # 安装缓存相关的两个包 diskcache 和 cassandra-driver import gzip from diskcache import FanoutCache, Disk from cassandra.cqltypes import BytesType from diskcache import FanoutCache,Disk,core from diskcache…