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

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...