设计模式:创建型设计模式、结构型设计模式
目录
- 前言
- 如何学习设计模式?
- 设计模式基础
- 设计原则
- 一. 创建型设计模式
- 1. 模板方法
- 2. 观察者模式
- 3. 策略模式
- 二. 结构型设计模式
- 1. 单例模式
- 2. 工厂模式
- 3. 抽象工厂
- 4. 责任链
- 5. 装饰器
- 6. 组合模式
前言
如何学习设计模式?
- 明确目的
- 在现有的设计模式上,拓展代码
- 在做功能抽象时,如何选择设计模式
- 学习步骤(由理解到使用)
- 该设计模式解决了什么问题:稳定点、变化点
- 该设计模式的代码结构是什么
- 该设计模式符合哪些设计原则
- 该设计模式上如何拓展代码
- 该设计模式有哪些典型应用场景
设计模式基础
- 设计模式是指在软件开发过程中,经过验证的,用于在特定环境下,重复出现的,特定问题的解决方案
- 设计模式是在满足设计原则后,慢慢迭代出来的
- 具体需求既有稳定点,又有变化点,才可以使用设计模式,期望修改少量的代码,就可以适应需求的变化
- 软件开发好比在一个房间里,有一只好动的猫,如何使房间保持整洁:把猫关在笼子里;使用设计模式,让变化点只能在有限的范围内变化
- 设计模式是与语言的特点有关的,就C++而言,面向对象的思想:封装(隐藏实现细节,实现模块化)、继承(无需修改原有类的情况下,通过继承实现对功能的扩展)、多态(函数重载、虚函数的重写…)
设计原则
- 依赖倒置:高层模块不应该依赖底层模块,两者都应该依赖抽象;抽象不应该依赖具体实现,具体实现应该依赖于抽象。
- 开放封闭:一个类应该对拓展(组合和继承)开放,对修改关闭。(封装、多态)
- 面向接口:不将变量类型声明为某个特定的类,而是声明为某个接口;使用者无需知道对象的具体类型,只需要知道对象所具有的接口;减少系统中各部分的依赖关系,从而实现“高内聚,松耦合”的类型设计方案(封装)
- 封装变化点:将稳定点和变化点分离,扩展修改变化点,让稳定点和变化点的实现层次分离(封装、多态)
- 单一职责:就一个类和接口而言,应该仅有一个引起它变化的原因(封装)
- 里氏替换:任何基类可以出现的地方,子类一定可以出现;子类必须完全实现父类的抽象方法,但不能覆盖父类的非抽象方法(多态)
- 接口隔离:类封装(权限限定词来实现),类与类的依赖通过接口进行联系(依赖注入)。
- 组合优于继承
- 最小知道原则:不对外暴露不需要的接口 。(封装)
设计原则之间有概念重复的部分,侧重点又有所不同;符合设计原则的代码,只需要修改少量的代码就可以演变成设计模式;因此在开发时,应参考设计原则进行代码结构设计
一. 创建型设计模式
1. 模板方法
- 定义一个操作中算法的骨架,而将一些步骤延迟到子类中;基类中有骨架流程接口,所有子流程对子类开放并且是虚函数
- 稳定点:算法的骨架,变化点:子流程需要变化
- Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
- 最常用的设计模式,子类可以复写父类子流程,使父类的骨架流程丰富
- 反向控制流程的经典应用
- 父类protected保护子类需要复写的子流程;这样子类的子流程只能父类来调用
2. 观察者模式
- 定义对象间的一种一对多(变化)的依赖关系,以便当一个对象的状态发生改变时,所有依赖它的对象都得到通知并自动更新
- 稳定点:“一”对“多”的依赖关系,“一”变化“多”跟着变化;变化点:“多”的数量增加或减少
- 观察者模式使得我们可以独立地改变目标与观察者,从而使二者之间的关系松耦合
- 观察者自己决定是否订阅通知,目标对象并不关注谁订阅了
- 观察者不依赖通知顺序,目标对象也不知道通知顺序
- 常用在基于事件的UI框架中,也是MVC的组成部分
- 常用在分布式系统中、actor框架中
3. 策略模式
- 定义一系列算法,把它们一个个封装起来,并且它们可互相替换。该模式使得算法可独立于使用它的客户程序而变化
- 稳定点:客户程序对算法的调用关系;变化点:算法
- 可以用来消除大量出现的if、else
- 策略模式提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换
- 策略模式消除了条件判断语句;也就是在解耦合
二. 结构型设计模式
1. 单例模式
- 保证一个类仅有一个实例,并提供一个该实例的全局访问点
- 稳定点:类只有一个实例,提供一个全局访问点 ;变化点:有多个类只需要创建一个实例,如何达成复用
- 禁用拷贝构造,拷贝赋值,移动构造,移动赋值
2. 工厂模式
- 定义一个用于创建对象的接口,让子类决定实例化哪一个类
- Factory Method使得一个类的实例化延迟到子类
- 稳定点:创建同类对象的接口(提供对象创建接口),并且同类对象只有一个相同的职责(提供一个功能接口);变化点:同类对象的个数
- 通常应用在创建过程比较复杂,并且希望对外隐藏这些细节的场景
- 比如连接池、线程池
- 希望隐藏对象的真实类型
- 对象创建会有很多参数来决定如何创建
- 创建对象有复杂的依赖关系
3. 抽象工厂
- 提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类
- 稳定点:创建同类对象的接口(提供对象创建接口),并且同类对象有多个相同的职责(提供多个功能接口);变化点:同类对象的个数
- 如果没有应对“多系列对象创建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂即可
- “系列对象”指的是在某个特定系列的对象之间有相互依赖、作用的关系。不同系列对象之间不能相互依赖
- 主要应用在“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动
4. 责任链
- 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
- 稳定点:请求按链条传递,并且会在链条的某一点上被处理;变化点:处理节点的个数,处理节点的顺序,处理的条件
- 解耦请求方和处理方,请求方不知道请求是如何被处理的,处理方的组成是由相互独立的子处理构成,子处理流程通过链表的方式连接,子处理请求可以按任意顺序组合
- 责任链请求强调请求最终由一个子处理流程处理;通过了各个子处理条件判断
- 责任链扩展就是功能链,功能链强调的是,一个请求依次经由功能链中的子处理流程处理
5. 装饰器
- 动态地给一个对象增加一些额外的职责。就增加功能而言,装饰器模式比生产子类更为灵活
- 稳定点:要为一个类增加职责且顺序无关;变化点:类的职责
- 通过组合而非继承的手法,装饰器模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生”问题
- 不是解决“多子类衍生”问题,而是解决“父类在多个方向上扩展功能”的问题
- 装饰器模式把一系列复杂的功能分散到每个装饰器当中,一般一个装饰器只实现一个功能,实现复用装饰器的功能
- 什么时候使用:在不影响其他对象的情况下,以动态、透明的方式给对象增加职责;每个职责都是完全独立的功能,彼此之间没有依赖
6. 组合模式
- 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性
- 稳定点:层次关系稳定,对象和组合对象的使用具有一致性;变化点:对象的职责变更,组合对象里的对象数量变更
- 如果想表示对象的部分-整体层次结构,可以选用组合模式,把整体和部分的操作统一起来,使得层次结构实现更简单,从外部来使用这个层次结构也更容易
- 如果希望统一地使用组合结构中的对象,可以选用组合模式,这正是组合模式提供的主要功能
相关文章:
设计模式:创建型设计模式、结构型设计模式
目录 前言如何学习设计模式?设计模式基础设计原则 一. 创建型设计模式1. 模板方法2. 观察者模式3. 策略模式 二. 结构型设计模式1. 单例模式2. 工厂模式3. 抽象工厂4. 责任链5. 装饰器6. 组合模式 前言 如何学习设计模式? 明确目的 在现有的设计模式上…...
如何选择多参数水质分析仪?
如何选择适合的多参数水质分析仪? 首先水质检测仪分为实验室(台式)和户外使用的便携式多参数水质检测仪。我们呢就要了解自己的需 求使用在什么领域,根据使用领域选择仪器;其次就是选择需要测定的指标,最好…...
明确自动化测试目的
明确自动化测试目的 1.提高测试人员的工作成就感和幸福感,减少手工测试中重复性的工作 目前,在大部分中小企业中,手工测试在日常测试工作占据的比例很大。测试人员必须跟随开发团队不断地进行选代式开发和测试。一个功能模块可能在整个测试周…...
DevExpress.XtraGrid.GridControl导出excel需要添加表头
string head ""; head "单号 \t" txtcCode.Text ; string foot ""; foot "制单人 \t" "制单日期 \t" "审核人: \t" "审核日期 \t" "修改人 \t&q…...
守护进程Daemon
进程组、对话期和控制终端关系 每个会话有且只有一个前台进程组,但会有0个或者多个后台进程组。产生在控制终端上的输入(Input)和信号(Signal)将发送给会话的前台进程组中的所有进程。对于输出(Output&…...
学生成绩管理系统 002
学生成绩管理系统 *****************学生成绩管理系统***************** 1、成绩添加 2、成绩输出 3、成绩查询 4、成绩统计 5、成绩排名 6、成绩删除 7、成绩修改 8、成绩按学号排序 0、退出系统 ************************************************** 请选择功能:1 **********…...
换个花样玩C++(4)细聊C++的引用精妙之处
引用是C++引入的新语言特性。而且在日常工作开发过程中,经常会使用到引用,对于一些做系统架构的架构师而言,这也是不可或缺的一门基本功,我在工作中发现,很多人并没有搞清楚引用。因此我在本篇中将对引用进行详细讨论,希望对大家更好地理解和使用引用起到抛砖引玉的作用。…...
Linux安装helm
前言 运行环境:CentOS7.9 官方参考文档:官方文档 文章末尾附有一键安装脚本 下载安装包 github下载对应版本的安装包,下载地址 进入对应版本的下载页面,这里以v3.11.3为例 选择对应系统的安装包,这里以linux为例 …...
ATTCK v12版本战术介绍——防御规避(四)
一、引言 在前几期文章中我们介绍了ATT&CK中侦察、资源开发、初始访问、执行、持久化、提权战术理论知识及实战研究、部分防御规避战术,本期我们为大家介绍ATT&CK 14项战术中防御规避战术第19-24种子技术,后续会介绍防御规避其他子技术…...
Orangepi Zero2 全志H616(DHT11温湿度检测)
最近在学习Linux应用和安卓开发过程中,打算把Linux实现的温湿度显示安卓app上,于是在此之前先基于Orangepi Zero2 全志H616下的wiringPi库对DHT11进行开发,本文主要记录开发过程的一些问题和细节,主要简单通过开启线程来接收温湿度…...
abbyy是什么软件
ABBYY,一款强大的OCR文字识别软件! 在日常的工作中,我们常常需要提取PDF或图片上的大段文字,如果字数少的话,我们可以直接手打,但如果出现大篇幅的文字,那就有点头疼了。今天,我就向…...
软件测试技术(四)白盒测试
白盒测试 白盒测试(White Box Testing)又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试只测试软件产品的内部结构和处理过程,而不测试软件产品的功能,用于纠正软件系统在描述、表示和规格上的错误,…...
Java基础语法(十二):try-catch块
目录 前言 一、try-catch是什么? 二、其他异常处理机制 总结 前言 Java 异常处理机制是 Java 程序设计中至关重要的一部分。它允许程序员像处理普通数据一样处理异常,并根据异常类型采取合适的措施。其中一个非常基本的异常处理机制是 try-catch 块…...
尚融宝25-投资列表展示以及实现充值功能
目录 一、展示投资列表 (一)需求 (二)后端 (三)前端 二、充值功能 (一)需求 1、需求描述 2、流程 (二)充值 1、后端 2、前端 (三&…...
QML基础模型(Basic Model)
最基本的分离数据与显示的方法是使用Repeater元素。它被用于实例化一组元素项,并且很容易与一个用于填充用户界面的定位器相结合。 最基本的实现举例,repeater元素用于实现子元素的标号。每个子元素都拥有一个可以访问的属性index,用于区分不…...
如果ChatGPT写作论文,保姆及教程以及问题答疑
上次发表“如何用ChatGPT完成论文”后,许多捧场看官评论讨论,也有不少同学实操成功,但更多人寻求帮助。所以今天再整理一篇,把大家的疑问进行说明。 1. ChatGPT写的论文能否被检查出? 有同学反映将一段ChatGPT…...
机器人中的数值优化(三)—— 无约束最优化方法基础、线搜索准则
本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,…...
vulnhub靶场之bluemoon
1.信息收集 存活主机进行探测,发现主机192.168.239.176存活。 对主机192.168.239.176进行端口扫描,发现21、22、80端口 访问http://192.168.239.176,并查看源码未发现可利用的行为。 进行目录扫描发现可疑路径/hidden_text 浏览器访问h…...
VTK 几何体连通区域分析 vtkPolyDataConnectivityFilter
前言: vtkPolyDataConnectivityFilter 使用过,但网上没有看到完事的教程;这里整理一下; 提取数据集中连通的多边形数据。 该类是一个滤波器,提取cell(区域) - 拥有公共点或者满足某个阈值 该类…...
scss、css样式中使用变量的方法;Vue动态改变css等样式文件中的变量
目录 一、问题 二、原因及解决方法 三、总结 一、问题 1.遇到一些样式 设置的值都是重复的不想重复写,想和js一样定义一个常量,然后直接引用这个常量。 2.想要在js中动态设置样式中的值,在 css、scss等样式表中直接使用。 二、原因及解…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
