设计模式学习笔记 - 回顾总结:在实际软件开发中常用的设计思想、原则和模式
概述
本章,先来回顾下整个专栏的知识体系,主要包括面向对象、设计原则、编码规范、重构技巧、设计模式五个部分。

面向对象
相对于面向过程、函数式编程,面向对象是现在最主流的编程范式。纯面向过程的编程方法,现在已经不多见了,而新的函数式编程,因为它的应用场景比较局限,所以大多作为面向对象编程的一种补充,用在科学技术、大数据处理等特殊领域。
面向对象提供了丰富的特性,比如封装、抽象、继承、多态,有助于实现复杂的设计思路,是很多设计原则、设计模式等编程实现的基础。
在面向对象第一部分,需重点掌握面向对象的四大特性:封装、抽象、继承、多态,以及面向对象编程与面向过程编程的区别。需要特别注意的是,在平时的面向对象编程开发中,我们要尽量避免写出面向过程风格的代码。
此外,还重点学习了面向对象分析(OOA)、设计(OOD)、编程(OOP)。其中,面向对象分析就是需求分析,面向对象设计就是代码层面设计,输出的设计结果是类。面向对象编程就是将设计的结果翻译成代码的过程。
在专栏中,重点讲解了面向对象设计这一部分。我们可以把面向对象设计分为四个环节:划分职责并识别出有哪些类、定义类的属性和方法、定义类之间的交互关系、组装类并提供执行入口。通过几个案例,带你实战了一下设计过程,希望你能面向开发需求时,不会无从下手,做到有章可循,按照我们给出的步骤,有条不紊地完成设计。
在面向对象这一部分,还额外讲到两个思想:基于接口而非实现编程设计思想、多用组合少用继承的设计思想。这两个设计思想虽然简单,但非常实用,应用它们能让代码更加灵活,更加容易扩展,所以,这两个设计思想几乎贯穿在我们整个专栏的代码中。
设计原则
在专栏的开始,我们总结了一套评判代码质量的标准,比如可读性、可维护性、可扩展性、复用性等,这是自从代码整理质量的角度来评判的。但是,落实到具体细节,我们往往是从是否符合设计原则,来对代码进行评判。比如,我们说这段代码的可扩展性比较差,主要原因是违背了开闭原则。也就是说,相对于可读性、可维护性、可扩展性等代码整体质量的评判标准,设计原则更加具体,能够更加明确地指出代码存在的问题。
在专栏中讲解的设计原则包括:SOLID 原则、DRY 原则、KISS 原则、YAGNI 原则、LOD 原则。这些原则的定义都很简单,看似很好理解,但也都比较抽象,比较难落地指导具体的编程。所以,学习的重点是透彻理解它们的设计初衷,找你给我它们能解决哪些编程问题,有哪些常用的应用场景。
SOLID 原则并非一个原则。它包含:单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)。其中,里氏替换和接口隔离这两设计原则并不那么常用,稍微了解即可。我们重点学习了单一职责、开闭、依赖倒置这三个原则。
单一职责原则是类职责划分的重要参考依据,是保证 “高内聚” 的有效手段,是面向对象设计前两步(划分职责并识别出有哪些类、定义类及其属性和方法)的主要指导原则。单一职责原则的难点在于,对代码职责是否足够单一的判定。这要根据具体的场景来具体分析。同一个类的设计,在不同的场景下,对职责是否单一的判定,可能是不同的。
开闭原则是保证代码扩展性的重要指导原则,是对代码扩展性的具体解读。很多设计模式诞生的初衷都是为了提高代码的扩展性,都是以满足开闭原则为设计目的。实际上,尽管开闭原则的描述为对扩展开放、对修改关闭,但也并不是说杜绝一切代码修改,正确的理解是以最小化修改代价来完成新功能的添加。实际上,在平时的开发中,我们要时刻思考,目前的设计在以后应对新功能扩展时,是否能做到不需要大的修改(比如调整代码接口)就能完成。
依赖倒置原则主要用来指导框架层面的设计。高层模块不依赖低层模块,它们共同依赖一个抽象。深挖一下的话,我们要把它和控制反转、依赖注入、依赖注入框架做区分。实际上,比依赖倒置原则更加常用的是依赖注入。它用来指导如何编写可测试性代码,换句话说,编写可测试代码的诀窍就是依赖注入。
KISS、YAGNI 可以说是两个万金油原则,小到代码、大到架构、产品,很多场景都能套用这两条原则。其中,YAGNI 原则表示暂时不需要的就不要做,KISS 原则表示要做就要尽量保持简单。跟单一职责原则类似,掌握这两个原则的难点在于,对代码是否符合 KISS、YAGNI 原则的判断,也需要根据具体的场景来具体分析,在某个时间点、某个场景下,某段代码符合 KISS、YAGNI 原则,换个时间、换个场景可能就不符合了。
DRY 原则主要是体现你不要写重复代码,这个倒不难掌握。LOD 原则又叫最小知道原则,不该有直接依赖关系的类不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。如果说单一职责原则是为了实现 “高内聚”,那这个原则就是为了实现 “松耦合”。
编码规范
编码规范很重要,特别是对于开发经验不多的程序员,遵从哈ode编码规范,能让你写出来的代码至少不会太烂。而且,编码规范都比较具体,不像设计原则、模式、思想那样比较抽象,需要融入很多个人的理解和思考。所以,它落地执行起来更加容易。
虽然我们讲了很多设计思想、原则、模式,但是,大部分代码都不需要用到这么复杂的设计,即便用到,可能也就是用到极个别的知识点,而且用的也不会很频繁。但是,编码规范就不一样了。编码规范影响到你写的每个类、函数、变量。你编写每行代码的时候都要思考是否符合编码规范。
此外,编码规范主要解决代码的可读性问题。在编写代码时,我们要把可读性放到首位。只有在代码可读性比较好的情况下,再去思考代码的扩展性、灵活性等。一般来说,一个可读性比较好的代码,对它修改、扩展、重构都不是难事,因为这些工作的前提都是先读懂代码。
不过,专栏只是总结了一些最常用的、最能明显改善代码质量的编码规范。你可以自己参考其他学习资料,比如《重构》、《代码大全》、《代码整洁之道》等书籍。
重构技巧
重构作为保证代码质量不腐化的有效手段,利用的是面向对象、设计原则、设计模式、编码规范这些理论。在重构过程中:
- 我们用到代码质量评判标准来评判代码的整体质量,
- 然后对照设计原则来发现代码存在的具体问题,
- 最后用设计模式或者编码规范对存在的问题进行改善。
持续重构除了能保证代码质量不腐化之外,还能有效地避免过度设计。有了持续重构意识,我们就不会因为担心设计不足和过度设计。我们先按照最简单的设计思路来设计,然后在后续的开发过程中逐步迭代重构。
我们还对重构进行了粗略的分类,分为大规模高层次的重构和小规模低层次的重构。不管哪种重构,保证重构不出错,除了熟悉代码之外,还有就是完善的单元测试。
设计模式
如果说设计原则相当于编程心法,那设计模式就相当于具体的招式。设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。我们用设计原则来评判代码设计有哪些问题,然后再通过具体的设计模式来改善。相对于其他部分来讲,设计模式时最容易学习的,但也是最容易被滥用的。所以,在《实际开发中如何避免过度设计,如何避免设计不足》章节,专门讲解了如何避免过度设计。
经典的设计模式有 23 中,分为三种类型:创建型、结构型和行为型。
- 创建型设计模式主要解决 “对象的创建” 问题,
- 结构型设计模式主要解决 “类或对象的组合” 问题,
- 行为型设计模式主要解决 “类或对象之间的交互” 问题。
虽然专栏中讲到的设计模式有很多,但常用的并不多,主要有:单例、工厂、建造者、代理、装饰器、适配器、观察者、模板、策略、职责链、迭代器这 11 种,所以,你只要集中精力,把这 11 种搞明白就可以了,剩下的那 12 种稍微了解,等到真正用到时,再深入地去研究学习就可以了
相关文章:
设计模式学习笔记 - 回顾总结:在实际软件开发中常用的设计思想、原则和模式
概述 本章,先来回顾下整个专栏的知识体系,主要包括面向对象、设计原则、编码规范、重构技巧、设计模式五个部分。 面向对象 相对于面向过程、函数式编程,面向对象是现在最主流的编程范式。纯面向过程的编程方法,现在已经不多见了…...
CPT7数据保存详细步骤
一、连接设备、打开NovAtelConnect 软件 (1)点击1,并在2中输入如下命令: LOG RANGEB ONTIME 1 // 输出原始数据记录在板卡LOG RAWEPHEMB ONTIME 1 // 输出 GPS 原始星历记录在板卡LOG bdsephemerisb ONTIME 1 // 输出...
物联网促进信息化——青创智通工业物联网解决方案
随着传感器网络(WSN)、无线射频识别(RFID)以及微电子机械系统(MEIVIS)等技术的不断成熟,扩展了人们对信息获取和使用的能力,并将提高制造效率、改善产品质量、降低产品成本和资源消耗、为用户提供更加透明和个性化的服…...
服务端Web资源缓存
1.前言 虽然客户端缓存效果很好,但它有一个核心问题:要在本地提供资源,必须先将其存储在缓存中。因此,每个客户端都需要其缓存的资源。如果请求的资源需要大量计算,则无法扩展。服务器端缓存背后的理念是计算一次资源…...
STM32-09-IWDG
文章目录 STM32 IWDG1. IWDG2. IWDG框图3. IWDG寄存器4. IWDG寄存器操作步骤5. IWDG溢出时间计算6. IWDG配置步骤7. 代码实现 STM32 IWDG 1. IWDG IWDG Independent watchdog,即独立看门狗,本质上是一个定时器,这个定时器有一个输出端&#…...
Android手动下载Gradle的使用方法
导入新项目通常会自动下载gradle版本,这种方式很慢而且经常下载失败,按照提示手动下载的gradle应该放在那里,如何使用,本篇文章为你提供一种亲测有效的方法: 在Android Studio打开Setting搜索Gradle找到Gradle的存放目…...
2024彩虹医械维修培训邀请
INVITATION 2024年5月20日 时间/TIME 地点/SITE (西安、成都) 随着我国医疗水平的提升,为适应现代医疗的发展步伐,提升医疗服务水平,各个医院在当下都开始重视医疗器械的维修。在医械行业,由于医疗器械…...
车辆超龄无法注册滴滴司机怎么办理账号
车辆超龄无法注册滴滴司机,别担心这个视频教你如何解决,滴滴司机注册过程中 车辆年限是一个常见的限制条件,如果您的车辆超过了8年,那么注册滴滴可能会遇到困难,但是不要因此而放弃成为滴滴司机的机会,《 …...
MATLAB车辆动力学建模 ——《控制系统现代开发技术》
引言 在上这门课之前,我已经用过CasADi 去做过最优化的相关实践,其中每一步迭代主要就是由:对象系统优化求解两部分组成的。这里我们重点介绍 “对象系统”如何去描述 ,因为它是每一步迭代中重要的一环——“优化求解”会获得控制…...
复杂json解析(其中有一个key的value是json格式的字符串)
app上报的参数如下: {"clientId": "8517895440514039afcf6d3e5d7832ae","dua": "SNDOCKCJPH90_GA&VN900042418&BN0&VCXiaomi&MOM2012K11AC&RL1080_2239&CHIDunknown_unknown&LCID&RV&OSAndroid13&…...
线程池的一些问题
核心线程数1.最大线程5.队列5.存活时间10s 1.场景一 如果核心线程数.被一直占用得不到释放.新进来1个任务.会怎么样?答: 会在队列中中死等. 只要进来的任务.不超过队列的长度,就会一直挡在队列中死等 package com.lin;import java.util.concurrent.Executors; import java.u…...
企业或者个体户为什么会经营异常?
在复杂多变的市场经济环境中,无论是企业还是个体工商户,都可能遭遇经营异常的情况。及时识别这些预警信号并采取有效措施,对于避免潜在风险、保持健康发展至关重要。本文将深入探讨企业与个体户常见的经营异常类型、识别方法以及应对策略&…...
ROS从入门到精通4-3:制作Docker镜像文件Dockerfile
目录 0 专栏介绍1 为什么需要Dockerfile?2 Dockerfile书写原则3 Dockerfile常用指令3.1 FROM3.2 MAINTAINER3.3 RUN3.4 ADD3.5 COPY3.6 CMD3.7 ENV3.8 EXPOSE3.9 WORKDIR3.10 ARG 4 Dockerfile构建ROS工程实例 0 专栏介绍 本专栏旨在通过对ROS的系统学习࿰…...
【CV】计算机视觉是什么?
计算机视觉是一门研究如何使机器“看”的学科,旨在实现从图像或视频中获取信息的技术和方法。它涵盖了图像处理、模式识别、机器学习等多个领域,是人工智能领域的重要分支之一。以下是计算机视觉的一般概要介绍: 概要介绍: 图像…...
如何在Vue中实现鼠标悬浮展示与隐藏弹窗的功能
如果你需要鼠标在元素和弹窗上时保持弹窗显示,而鼠标离开这两者时隐藏弹窗,你可以使用一个稍微复杂的逻辑来处理鼠标的进入和离开事件。 这通常涉及到延时关闭弹窗,以便给用户足够的时间从元素移动到弹窗上,而不触发弹窗关闭。以…...
03 Linux编程-进程
1、进程的相关概念 1.1 程序与进程 程序是静态的概念,进程是程序的一次运行活动。 1.2 查看系统中有哪些进程 ps #只显示一小部分进程 ps -aux #会打印当前所有进程 ps -aux|grep init #使用grep筛选出只含有init的进程top #运行显示的进程有点类似windows…...
Hbuild-X运行ios基座app
一、说明 ios真机第一次运行的时候需要下载插件,这个都是自动监测,自动下载的,不用多说。ios真机运行是需要签名的,不然就会报以下错误。如何制作免费的签名证书呢,需要借助爱思助手来完成。 二、安装爱思助手 &…...
Node.js基础:从入门到实战
初识 Node.js 与内置模块 (初识) 1、知道什么是node.js 2、知道node.js可以做什么 3、node.js 中js的组成部分 (内置模块) 4、用 fs 模块读写操作文件 5、使用 path 模块处理路径 6、使用http 模块写一个基本的web服务器 初识 N…...
考研408笔记总结~
目录 一.数据结构 二.计算机组成原理 三.操作系统 四.计算机网络 私以为边看视频,边做笔记会更专注些,大家需要自取。欢迎大家和我一起探讨考研的问题,包括不仅限于专业课,数学,英语等等......,想说什么…...
使用在线工具等方式下载推特视频
使用在线工具等方式下载推特视频 使用在线工具 Visit a Twitter video downloader website: Websites like twdown.net, twittervideodownloader.com, and savevideo.me offer services to download Twitter videos.Paste the Twitter video URL into the designated input bo…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
