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

【设计模式】六大基本原则

文章目录

  • 开闭原则
  • 里氏替换原则
  • 依赖倒置原则
  • 单一职责原则
  • 接口隔离原则
  • 迪米特原则
  • 总结

开闭原则

核心就一句话:对扩展开放,对修改关闭。

针对的目标可以是语言层面的类、接口、方法,也可以是系统层面的功能、模块。当需求有变化的时候,尽量不要动已经存在的核心代码,而是围绕核心代码做扩展升级。所以,在最开始的代码设计阶段,就应该适当考虑以后可能存在的扩展点,预留一定的可扩展空间。

遵循这条设计原则,就是要保证新增特性的时候尽量不影响已有的功能,提高系统的稳定性。

但是从长远来看,系统迭代发展到一定阶段,早期的设计和实现未必能满足现阶段的需求,有可能还会成为阻碍前进的障碍。这个时候就要考虑系统重构了,不要再顾虑开闭原则,不破不立。

里氏替换原则

里氏替换主要是讲继承和多态的设计原则,设计父子关系的时候,必须确保父类特性完全适用于子类。

通俗的解释,就是子类可以在父类的基础上新增和扩展功能,但绝对不要改变父类的基础本意。也就是说,子类可以新增独属于子类的方法和功能,也可以扩展细化父类提供的方法和功能,但就是不要违背父类的意志。

设计继承最根本的目的是为了运行时能够多态替换,其基础就是父子类具有相同的特性,父类出现的地方可以被子类替代。

依赖倒置原则

讲的是分层系统设计,层与层之间如何依赖的问题。

在以前的设计架构中,通常做法是高层模块依赖底层模块,先对底层模块进行独立设计和实现,然后让高层模块引入底层模块完成相关功能。慢慢的,就会发现其中一些问题:

  1. 底层模块的独立性更高,但是底层模块发生变动很有可能会影响到高层模块
  2. 高层模块的复用性更高,别的地方引入高层模块,就必须级联引入底层模块,这会使复用变的复杂

为了解决这些问题,就提出了依赖倒置原则,反过来,让底层模块依赖高层模块。由高层模块定义出抽象层接口,由底层模块实现这些接口。

也就是说,高层模块和底层模块都依赖于抽象层接口,这样做的好处:

  1. 高层模块只需依赖于抽象层接口,复用将会变的简单,底层模块不会被级联引入
  2. 底层模块也只依赖于抽象层接口,高层模块不变的情况下,替换底层模块将会变的容易

各种数据库驱动设计,就是一个典型的依赖倒置原则应用。

单一职责原则

这里是讲编程颗粒度的问题,小到一个类和接口,大到一个功能模块,都应该有且仅有一类变化因素,如果有很多不同的变化因素,就应该拆分颗粒度,直至它的变化因素唯一,这就是单一职责

如果一个颗粒度有太多的变化因素,可能会存在一些问题:

  1. 职责太多,职责之间可能会相互影响,任何一个职责变化都可能引发其它职责随之变化,牵一发而动全身
  2. 外界使用这个颗粒度,就必须引入全部职责,无论是否需要,这会造成职责冗余,还加深了非必要的联系

单一职责的核心就是颗粒度拥有合适的职责,提高代码实现的内聚性和灵活性。原则比较容易理解,但是想要拆分出适合的颗粒度,还是很考验开发人员的分析设计能力和相关重构经验的。

接口隔离原则

核心思想就是:要面向接口编程,不要面向实现编程。

无论是小功能还是大模块,都应该隐藏内部的代码实现,对外提供访问接口,通过接口声明它可以做的事情,功能之间、模块之间,都通过接口进行交流。

这样做的好处就是,内部实现代码是高内聚的,可以灵活调整和变通,只要接口层是稳定不变的,关联方就是无感知的,也就无需随之调整。

接口代表概念和逻辑,是抽象的,通常来讲,概念和逻辑是明确的,概念和逻辑的代码实现方式是千变万化的。所以,做系统设计的时候,首先要明确相关概念和逻辑,先用抽象层完成系统架构,再去依赖抽象层进行代码实现。

迪米特原则

形象的说法:只与你的朋友交谈,不要跟陌生人说话。

朋友是指熟悉可信任的对象,小到某个类和接口,大到功能模块系统,彼此可以直接调用和交流的都是朋友。

如果两个对象之间有交流的需求,但是又无法直接交流,或者不适合直接交流,就应用引入一个第三方作为中介,专门负责两边的沟通和联系。好处就是两边的模块都能保持各自的独立性,彼此的差异由中介去兼容和解决。

迪米特原则是系统间解耦的一种好思路,但是凡事都要有个度,过犹不及,如果引入了太多第三方中介,必然会增加系统链路之间的节点和长度,降低系统性能和稳定性,并且消息泄漏风险也会大幅增加。

总结

六大设计原则是前辈们总结出来的指导思想,合理灵活的运用能帮助我们构建出优秀的系统。但千万不要唯命是从,每个系统都有自己的重点和独特之处,结合实际情况完成设计和实现,取舍有度,适合自己的才是最好的。

相关文章:

【设计模式】六大基本原则

文章目录 开闭原则里氏替换原则依赖倒置原则单一职责原则接口隔离原则迪米特原则总结 开闭原则 核心就一句话:对扩展开放,对修改关闭。 针对的目标可以是语言层面的类、接口、方法,也可以是系统层面的功能、模块。当需求有变化的时候&#…...

Selenium网页的滚动

网页滚动功能实现 网页的滚动 如果需要对网页进行滑动操作,可以借助浏览器对象调用execute_script()方法来执行js语句,从而实现网页中的滚动下滑操作。 使用js语法实现网页滚动: # 根据x轴和y轴的值来定向滚动对应数值的距离 window.scrol…...

图算法系列1: 图算法的分类有哪些?(上)

大约在公元9世纪上半叶,来自中亚古国花剌子模的波斯数学家花剌子米(al-Khwarizmi)先后出版了两本对数学界有深远影响的书籍《印度数字算术》与《代数学》​,前者在12世纪被翻译为拉丁文传入欧洲,十进制也因此传入欧洲,最终所形成的…...

零样本学习——从多语言语料库数据中对未学习语言进行语音识别的创新技术

引言 在全球众多的语言中,只有极少数的语言在语音识别领域取得了显著的进展。这种不平衡现象的主要原因是,现有的语音识别模型往往依赖于大量的标注语音数据,而这些数据对于许多语言来说难以获得。 近年来,尽管语音识别技术取得…...

ViewStub的原理

**ViewStub是Android开发中的一个轻量级控件,主要用于懒加载布局以提高应用程序的性能和响应速度。**其原理和工作方式如下: 定义与特点 轻量级与不可见:ViewStub是一个不可见的、不占布局位置的轻量级View,它在初始化时不会实例…...

十一、Spring AOP

十一、Spring AOP 1. AOP概述2. Spring AOP快速⼊⻔2.1 引⼊AOP依赖2.2 编写AOP程序 3. Spring AOP 详解3.1 Spring AOP核⼼概念3.1.1 切点(Pointcut) Around 哪个包3.1.2 连接点(Join Point) 包下面的方法3.1.3 通知(Advice) 就是要执行的方法3.1.4 切⾯(Aspect) 3.2 通知类型…...

【网络】IP的路径选择——路由控制

目录 路由控制表 默认路由 主机路由 本地环回地址 路由控制表的聚合 网络分层 个人主页:东洛的克莱斯韦克-CSDN博客 路由控制表 在数据通信中,IP地址作为网络层的标识,用于指定数据包的目标位置。然而,仅有IP地址并不足以确…...

Unity动画模块 之 2D IK(反向动力学)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​ 1.什么是IK 反向动力学 IK(Inverse Kinematics)是一种方法,可以根据某些子关节的最…...

关于kickstart自动安装脚本以及dhcp的设置

我将在rhel7.9内进行本次实验,需要安装并启动图形界面 hostnamectl查看是否有图形界面 没有的话 可以使用yum group list 查看,并安装server with GUI yum group install "server with GUI" -y安装完成后可以使用init 5启动 安装kickstart自…...

AWS云服务器选择最佳区域

2024年,随着全球云计算的持续发展和AWS在全球不断扩展的数据中心网络,选择合适的AWS云服务器区域成为了企业和开发者需要认真考虑的问题。九河云告诉你在做出选择之前,需要考虑以哪些关键因素: 地理位置和用户分布 选择AWS云服务…...

Unity Android端截图保存并获取展示

截屏保存方法 public static IEnumerator ScreenShot(string filePath, string fileName){yield return new WaitForEndOfFrame();Rect rect new Rect(0, 0, Screen.width, Screen.height);Texture2D screenShot new Texture2D(Screen.width, Screen.height, TextureFormat.R…...

linux高级编程——文件IO

linux高级编程——文件IO 标准IO:stdio.h 标准IO:stdio.h IO也就是输入input和输出output; I: 键盘是标准输入设备,默认输入就是指键盘 /dev/input; O: 显示器是标准输出设备,默认输…...

windows C++-在 C++/WinRT 中使用委托处理事件(下)

撤销已注册的委托 当你注册委托时,通常会向你返回一个令牌。 随后,可以使用该令牌撤销委托;这意味着将从事件取消注册委托,再次引发该事件时不会调用该委托。 为简单起见,上面的代码示例都没有介绍如何执行该操作。 …...

【实用工具】Stirling-PDF: 优质开源的PDF处理工具/编辑工具-含入门安装教程

文章目录 项目简介功能展示Page Operations 页面操作Conversion Operations 转换操作Security & Permissions 安全与权限Other Operations 其他业务 如何安装并使用Docker RunDocker Compose 项目简介 这是一款使用 Docker 的基于本地托管网络的强大 PDF 操作工具。它能让…...

opencv 深度图视差图可视化案例

参考:https://www.cnblogs.com/zyly/p/9373991.html(图片这里面下载的) https://blog.csdn.net/He3he3he/article/details/101053457 原理 双目摄像头 视差公式: 三角形对应推算 深度距离转换: 这里d是视差Disparity 代码 下面两种计算视差方法: import os impor…...

Golang | Leetcode Golang题解之第330题按要求补齐数组

题目&#xff1a; 题解&#xff1a; func minPatches(nums []int, n int) (patches int) {for i, x : 0, 1; x < n; {if i < len(nums) && nums[i] < x {x nums[i]i} else {x * 2patches}}return }...

算法训练(leetcode)第五十二天 | Bellman_ford 队列优化算法(SPFA)、BF算法判断负回路、BF之单源有限最短路(有负回路)

刷题记录 94. 城市间货物运输 I-Bellman_ford 队列优化算法&#xff08;SPFA&#xff09;95. 城市间货物运输 II-BF算法判断负回路96. 城市间货物运输 III-BF之单源有限最短路(有负回路) 94. 城市间货物运输 I-Bellman_ford 队列优化算法&#xff08;SPFA&#xff09; 题目地址…...

SpringBoot中整合RabbitMQ(测试+部署上线 最完整)

一、RabbitMQ安装 由于在测试环境中&#xff0c;我们现在虚拟机上基于docker安装mq docker run \-e RABBITMQ_DEFAULT_USERquick \-e RABBITMQ_DEFAULT_PASS123 \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network your-net\-d \r…...

算法板子:线性DP——算出三角形中的最大路径值、求最长上升子序列、求最长公共子序列

目录 一、数字三角形——算出三角形中的最大路径值 二、最长上升子序列——求一个数组中的最长递增子序列 三、最长公共子序列——求两个字符串中的最长公共子序列 一、数字三角形——算出三角形中的最大路径值 #include <iostream> using namespace std;const int N …...

【C++】值传递

函数值传递的特点&#xff1a;值传递过程中即使形参改变也不会改变实参 没有返回值的函数用“ void ”定义 下面是一个实例&#xff1a; #include<iostream> using namespace std;//值传递 //定义函数&#xff0c;实现两个数字进行交换函数//如果函数不需要返回值&…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...