当前位置: 首页 > 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++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...