【设计模式】结构型设计模式

结构型设计模式

文章目录

  • 结构型设计模式
    • 一、概述
    • 二、适配器模式(Adapter Pattern)
      • 2.1 类适配器模式
      • 2.2 对象适配器模式
      • 2.3 接口适配器模式
      • 2.4 小结
    • 三、桥接模式(Bridge Pattern)
    • 四、装饰器模式(Decorator Pattern)
    • 五、组合模式(Composite Pattern)
    • 六、外观模式(Facade Pattern)
    • 七、享元模式(Flyweight Pattern)
    • 八、代理模式(Proxy Pattern)
    • 九、依赖注入模式 *(Dependency Injection)
    • 十、流接口模式 *(Fluent Interface)

一、概述

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

  • 适配器模式(Adapter Pattern)
  • 桥接模式(Bridge Pattern)
  • 装饰器模式(Decorator Pattern)
  • 组合模式(Composite Pattern)
  • 外观模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)
  • 代理模式(Proxy Pattern)
  • 依赖注入模式 *(Dependency Injection)
  • 流接口模式 *(Fluent Interface)

二、适配器模式(Adapter Pattern)

  1. 适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)
  2. 主要分为三类:类适配器模式对象适配器模式接口适配器模式

2.1 类适配器模式

Adapter类,通过继承 src类,实现 dst 类接口,完成src->dst的适配。

以手机充电器为例子:

在这里插入图片描述

充电器本身相当于Adapter,220V交流电相当于src (即被适配者),dst(即目标)是5V直流电

2.2 对象适配器模式

  1. 基本思路和类的适配器模式相同,只是将Adapter类作修改,不是继承src类,而是持有src类的实例,以解决兼容性的问题。 即:持有 src类,实现 dst 类接口,完成src->dst的适配
  2. 根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系
  3. 对象适配器模式是适配器模式常用的一种
public class VoltageAdapter2 implements Voltage5 {private Voltage220 voltage220; //持有Voltage220对象,不是继承了
}

2.3 接口适配器模式

当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。在使用Java做页面监听时经常会碰到对应适配类。

2.4 小结

  1. 三种命名方式,是根据 src是以怎样的形式给到Adapter(在Adapter里的形式)来命名的。
    1. 类适配器:以类给到,在Adapter里,就是将src当做类,继承
    2. 对象适配器:以对象给到,在Adapter里,将src作为一个对象,持有
    3. 接口适配器:以接口给到,在Adapter里,将src作为一个接口,实现
  2. Adapter模式最大的作用还是将原本不兼容的接口融合在一起工作。
  3. 实际开发中,实现起来不拘泥于这三种经典形式

三、桥接模式(Bridge Pattern)

  1. 桥接模式(Bridge 模式)是指:是将抽象部分与它的具体实现部分分离,使它们都可以独立地变化。
  2. Bridge 模式基于类的最小设计原则,通过组合/聚合的方式建立两个类之间的联系,而不是继承。但又类似于多重继承方案,但是多重继承方案往往违背了类的单一职责原则,其复用性较差,桥接模式是比多重继承更好的替代方案。桥接模式的核心在于解耦抽象和实现。

在这里插入图片描述

  1. Client 类:桥接模式的调用者
  2. 抽象类(Abstraction) :维护了 Implementor / 即它的实现类 ConcreteImplementorA…, 二者是聚合关系, Abstraction充当桥接类
  3. RefinedAbstraction : 是 Abstraction 抽象类的子类
  4. Implementor : 行为实现类的接口
  5. ConcreteImplementorA /B :行为的具体实现类
  6. 从 UML 图:这里的抽象类和接口是聚合的关系,其实是调用和被调用关系

上面概念比较抽象,这里以手机为例:

  1. 首先有需求,手机可以按品牌分:HuaWei、Vivo、XiaoMi,不同品牌对应着不同的应用商城
  2. 业务需求变更,对于手机型号有了区分,分为A、B、C型,不按桥接模式设计,则需要多重继承实现功能全排序,不同品牌对应不同型号共9个实现
  3. 按桥接模式设计,新建一个桥接抽象类为Phone,其实现类分别为A、B、C型,有不同的功能,通过聚合关系,将品牌实现接口聚合到Phone抽象类中,这样只需新增3个实现类;而手机的型号以及品牌又可以区分开来,分别运用其不同特别功能

常见应用场景

  1. JDBC 驱动程序
  2. 银行转账系统
    • 转账分类: 网上转账,柜台转账,AMT 转账
    • 转账用户类型:普通用户,银卡用户,金卡用户
  3. 消息管理
    • 消息类型:即时消息,延时消息
    • 消息分类:手机短信,邮件消息,QQ 消息…

四、装饰器模式(Decorator Pattern)

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。

典型的应用就是jdk中IO流的应用,FilterInputStream 就是一个装饰者,BufferInputStream是具体的实现类,通过组合的关系,使得输入流有了缓冲的功能,而又无需修改原有inputStream代码。

在这里插入图片描述

五、组合模式(Composite Pattern)

组合模式就运用了树形结构,该模式的核心思想是:将多个对象组合成树形结构,以此结构来表示“整体-部分”之间的层次关系。

在这里插入图片描述

  1. 抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性
  2. 树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一 个树形结构
  3. 叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位

应用场景:

  1. 组合-部分整体场景:将多个对象组合成一个整体,并且整体与部分是一致对待的。比如树形菜单、文件夹和文件等
  2. 递归结构场景:处理递归的数据结构。比如文件和目录的关系就是递归的
  3. 规则场景:当需要处理的对象具有明显的层次结构时,可以考虑使用组合模式。比如,企业中不同职位的员工,每个职位的员工都有一些共同的属性(比如姓名、公司邮件地址),但也有一些不同的属性(比如职位、薪水等)
  4. 任务分解场景:将一个大任务分解为多个小任务,然后再将小任务组合起来,形成一个任务树。这种情况下,可使用组合模式对任务进行建模
  5. GUI控件场景:GUI控件通常可以嵌套在其他控件中,并且用户可以在控件中插入其他控件,组合模式适用于GUI控件的场景

组合模式适用于处理树形结构的场景,将一个对象的部分和整体看作一样,形成一个树形结构。在需要统一处理整个树形结构时,可以考虑使用组合模式。

六、外观模式(Facade Pattern)

外观模式(Facade),也叫过程模式:外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口。

外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节。这个模式我们平时就会使用,比如调用交易接口,交易接口中会再去调用其他各个接口。或者MVC模式下我们写的Controller,即对外暴露接口,前端开发无需关心后端干了什么。

在这里插入图片描述

  1. 通过合理的使用外观模式,可以帮我们更好的划分访问的层次
  2. 在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个 Facade 类,来提供遗留系统的比较清晰简单的接口,让新系统与 Facade 类交互,提高复用性
  3. 不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好。要以让系统有层次,利于维护为目的

七、享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern) 也叫 蝇量模式: 运用共享技术有效地支持大量细粒度的对象。

享元模式经典的应用场景就是池技术了,String 常量池、数据库连接池、缓冲池等等都是享元模式的应用,享元模式是池技术的重要实现方式

在这里插入图片描述

  1. FlyWeight 是抽象的享元角色, 他是产品的抽象类, 同时定义出对象的外部状态和内部状态(后面介绍) 的接口或实现
  2. ConcreteFlyWeight 是具体的享元角色,是具体的产品类,实现抽象角色定义相关业务
  3. UnSharedConcreteFlyWeight 是不可共享的角色,一般不会出现在享元工厂
  4. FlyWeightFactory 享元工厂类,用于构建一个池容器(集合), 同时提供从池中获取对象方法,这个一般被设计为单例模式

内部状态是不会变化的,可以被多个对象共享,而外部状态会随着对象的使用而改变。比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接URL等信息,在创建对象的时候就设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。

八、代理模式(Proxy Pattern)

代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

在这里插入图片描述

代理模式有不同的形式, 主要有三种 静态代理动态代理 (JDK 代理、接口代理)和 Cglib 代理 (可以在内存动态的创建对象,而不需要实现接口, 他是属于动态代理的范畴)。最经典的运用即Spring的AOP。

九、依赖注入模式 *(Dependency Injection)

依赖注入(Dependency Injection)是控制反转(Inversion of Control)的一种实现方式。

我们先来看看什么是控制反转。当调用者需要被调用者的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例,但在这里,创建被调用者的工作不再由调用者来完成,而是将被调用者的创建移到调用者的外部,从而反转被调用者的创建,消除了调用者对被调用者创建的控制,因此称为控制反转。

要实现控制反转,通常的解决方案是将创建被调用者实例的工作交由 IoC 容器来完成,然后在调用者中注入被调用者(通过构造器/方法注入实现),这样就实现了调用者与被调用者的解耦,该过程被称为依赖注入。依赖注入不是目的,它是一系列工具和手段,最终的目的是帮助开发出松散耦合(loose coupled)、可维护、可测试的代码和程序。这条原则的做法是大家熟知的面向接口,或者说是面向抽象编程。典型应用案例即Spring中使用@Autowize 注解实现属性注入。

个人感觉这种模式和注册模式类似,都是通过统一容器收纳注册对象,调用方直接通过注册容器调用接口,具体实现类则由容器返回。故不再对注册模式分析。

十、流接口模式 *(Fluent Interface)

在软件工程中,流接口(Fluent Interface)是指实现一种面向对象的、能提高代码可读性的 API 的方法,其目的就是可以编写具有自然语言一样可读性的代码,我们对这种代码编写方式还有一个通俗的称呼 —— 方法链。

最常见的就是Lombak注解中,@Builder 或者 @Accessors(chain=true) 开启链式编程,即可通过方法链调用的方式设置实体类的属性。

// 用简洁的方式实例化实体类并完成赋值操作,而无需多行不断调用set方法
XUser xUser = XUser.builder().userId(1).userName("AAAAA").build();

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

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

相关文章

基于ubuntu20.04安装ros系统搭配使用工业相机

基于ubuntu20.04安装ros系统搭配使用工业相机 1. ROS系统安装部署1.1更新镜像源1.1.1 备份源文件1.1.2 更新阿里源1.1.3 更新软件源 1.2 ros系统安装1.2.1 添加ros软件源1.2.2 添加秘钥1.2.3 更新软件源1.2.4 配置及更换最佳软件源1.2.5 ROS安装1.2.6 初始化rosdep1.2.7 设置环…

datagrip只导出表结构

话不多说,直接上教程。 datagrip版本:2022.3 第一步,连接数据库 第二步,右击数据库,复制即可

【20年扬大真题】编写对数组求逆的递归算法

【20年扬大真题】 编写对数组求逆的递归算法 void swap(int* a, int* b) {int tmp *b;*b *a;*a tmp; } void Ni(int arr[],int left,int right) {if (left > right) {return;}swap(&arr[left], &arr[right]);Ni(arr, left 1, right - 1); } int main() {int ar…

详解Python安装requests库的实例代码

文章目录 前言基本用法基本的get请求带参数的GET请求解析json关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 前…

“茶叶创新:爆改营销策略,三个月狂销2300万“

我的朋友去年制作了一款白茶,并在短短三个月内将其销售量推到了2300万的高峰。你相信吗? 这位朋友并没有任何茶叶方面的经验,他只是一个有着冒险精神的企业家。他先找到了一家代工厂,帮助他把他的茶叶理念转化为现实。 当他把茶叶…

win11,安装python,pip,和opencv

1,安装python 在应用商店,输入python,下载安装 2,安装pip 在cmd中,输入pip install SomePackage,安装某一个版本的pip 3,安装opencv 在cmd中,输入 pip3 install opencv-contrib-python -i https://pyp…

【Python】153是一个非常特殊的数,它等于它的每位数字的立方和,即153=1*1*1+5*5*5+3*3*3。编程求所有满足这种条件的三位十进制数。

问题描述 153是一个非常特殊的数,它等于它的每位数字的立方和,即1531*1*15*5*53*3*3。编程求所有满足这种条件的三位十进制数。 输出格式 按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。 方法一: for i in range(10…

私域运营如何提高收益?

一旦建立了私域之后,企业需要不断地进行数据统计与分析,以寻找提高收益的方法。通过收集和分析用户的信息,了解他们的购物行为、心理需求等,从而制定更符合顾客口味的促销计划和产品服务。只有持续对数据进行监控,才能…

深度学习之基于Pytorch的昆虫分类识别系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介系统架构技术亮点 二、功能三、系统四. 总结 一项目简介 # 深度学习基于 Pytorch 的昆虫分类识别系统介绍 深度学习在图像分类领域取得了显著的成就&#…

ArcGIS Pro 优化的热点分析【Optimized Hot Spot Analysis】

ArcGIS Pro 优化的热点分析【Optimized Hot Spot Analysis】Optimized Hot Spot Analysis 优化的热点分析https://mp.weixin.qq.com/s/lfoIls8exW5G6PPJ9gtDew em,先给大家推荐一个空间统计分析的学习资源网站 https://spatialstats-analysis-1.hub.arcgis.com/ .…

策略选股辅助工具(八)

8-策略选股辅助工具 文章目录 8-策略选股辅助工具一. 查询某个股票日常分析数据的信息二. 查询可以做T的股票的策略信息三. 查询股票K线类型四. 查询策略因子筛选股票信息五. 查询日K数据 处理成 Pdf图信息六. 根据股票的编码和日期获取那段时间的所有的数据信息 一. 查询某个股…

[oeasy]python001_先跑起来_python_三大系统选择_windows_mac_linux

先跑起来 🥊 Python 什么是 Python? Python [ˈpaɪθɑ:n]是 一门 适合初学者 的编程语言 类库 众多 几行代码 就能 出 很好效果 应用场景丰富 在 各个应用领域 都有 行内人制作的 python 工具类库 非常专业、 好用 特别是 人工智能领域 pytho…

渲染器——双端Diff算法

简单 Diff 算法利用虚拟节点的 key 属性,尽可能地复用 DOM 元素,并通过移动 DOM 的方式来完成更新,从而减少不断地创建和销毁DOM 元素带来的性能开销。但是,简单 Diff 算法仍然存在很多缺陷,这些缺陷可以通过双端 Diff…

【阿里云】图像识别 摄像模块 语音模块

USB 摄像头模块测试及配置 一、首先将 USB 摄像头插入到 Orange Pi 开发板的 USB 接口中二、然后通过 lsmod 命令可以看到内核自动加载了下面的模块三、通过 v4l2-ctl 命令可以看到 USB 摄像头的设备节点信息为 /dev/video0四、使用 fswebcam 测试 USB 摄像头五、使用 motion …

chrome内置路径合集

设置黑夜模式: 输入网址:chrome://flags/ 搜索dark 改为enable 实验项目路径 chrome://flags/ 可用来启用或者关闭某些 Chrome 的实验功能 chrome://settings 将快速打开 Chrome 浏览器的设置页面,页面的内容分类划分为基础和高级设置选项 …

以太网_底层

【实物图】 【网线接口】 MAC(媒体访问控制器):控制数据的收发和管理,和用户层打交到;通过MII/RMII、SMI接口和PHY进行通信。 PHY(以太网物理层收发器):中间体,负责收发信号的转换 常见PHY芯片有:LAN8720…

PIL如何批量给图片添加文字水印?

PIL如何批量给图片添加文字水印? 1 简单引入2 关于PIL3 本文涉及的PIL的几个类4 实现原理5 实现过程5.1 原始图片5.2 导入相关模块5.3 初始化数据5.4 水印字体设置5.5 打开原始图片并新建存储对象5.6 计算图片和水印的大小5.7 选择性设置水印文字5.8 绘制文字并设置…

基于yolov8的车牌检测训练全流程

YOLOv8 是Ultralytics的YOLO的最新版本。作为一种前沿、最先进(SOTA)的模型,YOLOv8在之前版本的成功基础上引入了新功能和改进,以提高性能、灵活性和效率。YOLOv8支持全范围的视觉AI任务,包括检测, 分割, 姿态估计, 跟踪, 和分类。这种多功能…

Java项目实战《苍穹外卖》 三、登录功能

测测你是什么人格吧,地址: MBTI 16种人格测试官网 系列文章目录 苍穹外卖是黑马程序员2023年的Java实战项目,作为业余练手用,需要源码或者课程的可以找我,无偿分享 Java项目实战《苍穹外卖》 一、项目概述Java项目实战…

Redis从入门到精通(三)-高阶篇

文章目录 0. 前言[【高阶篇】3.1 Redis协议(RESP )详解](https://blog.csdn.net/wangshuai6707/article/details/132742584)[【高阶篇】3.3 Redis之底层数据结构简单动态字符串(SDS)详解](https://blog.csdn.net/wangshuai6707/article/details/131101404)[【高阶篇】3.4 Redis…