当前位置: 首页 > 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;实现两个数字进行交换函数//如果函数不需要返回值&…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...