设计模式三原则

1.1单一职责原则

        C++ 面向对象三大特性之一的封装指的就是将单一事物抽象出来组合成一个类,所以我们在设计类的时候每个类中处理的是单一事物而不是某些事物的集合。

        设计模式中所谓的单一职责原则,就是对一个类而言,应该仅有一个引起它变化的原因,其实就是将这个类所承担的职责单一化,如果一个类承担的职责过多,就等于把这些职责耦合到了一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致设计变得脆弱,当变化发生时,设计会遭受到意想不到的破坏。

        软件设计真正要做的事情就是,发现根据需求发现职责,并把这些职责进行分离,添加新的类,给当前类减负,越是这样项目才越容易维护。

1.2开放封闭原则

        开放 – 封闭原则说的是软件实体(类、模块、函数等)可以扩展,但是不可以修改。也就是说对于扩展是开放的,对于修改是封闭的。

        该原则是程序设计的一种理想模式,在很多情况下无法做到完全的封闭。但是作为设计人员,应该能够对自己设计的模块在哪些位置产生何种变化了然于胸,因此需要在这些位置创建抽象类来隔离以后发生的这些同类变化(其实就是对多态的应用创建新的子类并重写父类虚函数,用以更新处理动作)。此处的抽象类,其实并不等价于 C++ 中完全意义上是抽象类(需要有纯虚函数),这里所说的抽象类只需要包含虚函数(纯虚函数或非纯虚函数)能够实现多态即可

        开放 – 封闭原则是面向对象设计的核心所在,这样可以给我们设计出的程序带来巨大的好处,使其可维护性、可扩展性、可复用性、灵活性更好

1.3依赖倒转原则(对多态的典型应用)

关于依赖倒转原则,对应的是两条非常抽象的描述:

1.高层模块不应该依赖低层模块,两个都应该依赖抽象。

 2.抽象不应该依赖细节,细节应该依赖抽象。

先用人话解释一下这两句话中的一些抽象概念:

  • 高层模块:可以理解为上层应用,就是业务层的实现,编写的应用程序
  • 低层模块:可以理解为底层接口,比如封装好的 API、动态库等
  • 抽象:指的就是抽象类或者接口,在 C++ 中没有接口概念(Java里有),只有抽象类(在设计模式里的抽象类没有那么严格,可以为虚函数或纯虚函数),C++中定义接口的方法是在父类定义虚函数,在子类中重写虚函数。

举一个高层模块依赖低层模块的例子:

        大聪明的项目组接了一个新项目,低层使用的是 MySql 的数据库接口,高层基于这套接口对数据库表进行了添删查改,实现了对业务层数据的处理。而后由于某些原因,要存储到数据库的数据量暴增,所以更换了 Oracle 数据库,由于低层的数据库接口变了,高层代码的数据库操作部分是直接调用了低层的接口,因此也需要进行对应的修改,无法实现对高层代码的直接复用,大聪明欲哭无泪。

        解决方法是高层和底层代码之间设计好抽象类和抽象类子类,写好调用MySQL的抽象子类,当底层换成Oracle数据库时,只需要增加调用Oracle的抽象子类,从而减少工作量。        

        通过上面的例子可以得知,当依赖的低层模块变了就会牵一发而动全身,如果这样设计项目架构,对于程序猿来说,其工作量无疑是很重的。如果要搞明白这个案例的解决方案以及抽象和细节之间的依赖关系,需要先了解另一个原则——里氏代换原则

里氏代换原则

里氏代换原则就是子类类型必须能够替换掉它们的父类类型。

关于这个原理的应用其实也很常见,比如在 Qt 中,所有窗口类型的类的构造函数都有一个 QWidget* 类型的参数(QWidget 类是所有窗口的基类),通过这个参数指定当前窗口的父对象。虽然参数是窗口类的基类类型,但是我们在给其指定实参的大多数时候,指定的都是子类的对象,其实也就是相当于使用子类类型替换掉了它们的父类类型。

上面在讲依赖倒转原则的时候说过,抽象不应该依赖细节,细节应该依赖抽象。也就意味着我们应该对细节进行封装,在 C++ 中就是将其放到一个抽象类中(C++ 中没有接口,不能像 Java 一样封装成接口),每个细节就相当于上面例子中的哺乳动物的一个特性,这样一来这个抽象的哺乳动物类就成了项目架构中高层和低层的桥梁,将二者整合到一起。

  • 抽象类中提供的接口是固定不变的
  • 低层模块是抽象类的子类,继承了抽象类的接口,并且可以重写这些接口的行为
  • 高层模块想要实现某些功能,调用的是抽象类中的函数接口,并且是通过抽象类的父类指针引用其子类的实例对象(用子类类型替换父类类型),这样就实现了多态。

 基于依赖倒转原则将项目的结构换成上图的这种模式之后,低层模块发生变化,对应高层模块是没有任何影响的,这样程序猿的工作量降低了,代码也更容易维护(说白了,依赖倒转原则就是对多态的典型应用)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/90923.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

我的128天创作纪念日-东离与糖宝

文章目录 机缘收获日常成就憧憬 不知不觉我也迎来了自己的128天创作纪念日,一起来看看我有什么想对大家说的吧 机缘 我的写博客之旅始于参加了代码随想录算法训练营。在训练营期间,代码随想录作者卡尔建议我们坚持每天写博客记录刷题学习的进度和心得体…

【LeetCode-中等题】240. 搜索二维矩阵 II

文章目录 题目方法一:暴力双for查找方法二:二分查找,对每二维数组进行拆分,一行一行的进行二分查找方法三:列倒序Z字形查找 题目 方法一:暴力双for查找 public boolean searchMatrix(int[][] matrix, int …

Java版B/S架构 智慧工地源码,PC、移动、数据可视化智慧大屏端源码

智慧工地是什么?智慧工地主要围绕绿色施工、安全管控、劳务管理、智能管理、集成总控等方面,帮助工地解决运营、管理方面各个难点痛点。在互联网的加持下促进项目现场管理的创新与发展,实现工程管理人员与工程施工现场的整合,构建…

系统架构师---软件重用、基于架构的软件设计、软件模型

目录 软件重用 构件技术 基于架构的软件设计 ABSD方法与生命周期 抽象功能需求 用例 抽象的质量和业务需求 架构选项 质量场景 约束 基于架构的软件开发模型 架构需求 需求获取 标识构件 需求评审 架构设计 架构文档 架构复审 架构实现 架构演化 前言&…

什么是响应式设计(Responsive Design)?如何实现一个响应式网页?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 响应式设计(Responsive Design)⭐ 如何实现一个响应式网页?1. 弹性网格布局2. 媒体查询3. 弹性图像和媒体4. 流式布局5. 优化导航6. 测试和调整7. 图片优化8. 字体优化9. 渐进增强10. 面向移动优先11. …

一、Kafka概述

目录 1.1 定义1.2 消息队列1、传统消息队列的应用场景2、消息队列的两种模式 1.3 Kafka的基础架构 1.1 定义 Kafka传 统定义:Kafka是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于大数据实时处理领域。 K…

6、Spring_Junit与JdbcTemplate整合

Spring 整合 1.Spring 整合 Junit 1.1新建项目结构 1.2导入依赖 导入 junit 与 Spring 依赖 <!-- 添加 spring 依赖--> <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version…

数据结构数组栈的实现

Hello&#xff0c;今天我们来实现一下数组栈&#xff0c;学完这个我们又更进一步了。 一、栈 栈的概念 栈是一种特殊的线性表&#xff0c;它只允许在固定的一端进行插入和删除元素的操作。 进行数据的插入和删除只在栈顶实现&#xff0c;另一端就是栈底。 栈的元素是后进先出。…

前端高频面试题 js中堆和栈的区别和浏览器的垃圾回收机制

一、 栈(stack)和 堆(heap) 栈(stack)&#xff1a;是栈内存的简称&#xff0c;栈是自动分配相对固定大小的内存空间&#xff0c;并由系统自动释放&#xff0c;栈数据结构遵循FILO&#xff08;first in last out&#xff09;先进后出的原则&#xff0c;较为经典的就是乒乓球盒结…

验证码服务(使用提供好的项目)

1、先生成一个指定位数的验证码&#xff0c;根据需要可能是数字、数字字母组合或文字。 2、根据生成的验证码生成一个图片并返回给页面 3、给生成的验证码分配一个key&#xff0c;将key和验证码一同存入缓存。这个key和图片一同返回给页面。 4、用户输入验证码&#xff0c;连…

iPhone 15 Pro与谷歌Pixel 7 Pro:哪款相机手机更好?

考虑到苹果最近将更多高级功能转移到iPhone Pro设备上的趋势,今年秋天iPhone 15 Pro与谷歌Pixel 7 Pro的对决将是一场特别有趣的对决。去年发布的iPhone 14 Pro确实发生了这种情况,有传言称iPhone 15 Pro再次受到了苹果的大部分关注。 预计iPhone 15系列会有一些变化,例如切…

新版Jadx 加载dex报错 jadx.plugins.input.dex.DexException:Bad checksum 解决方法

本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!新版Jadx(1.6+) 加载dex报错 jadx.plugins.input.dex.DexException:Bad checksum 解决方法 环境 win10J…

QT5.12.12通过ODBC连接到GBase 8s数据库(CentOS)

本示例使用的环境如下&#xff1a; 硬件平台&#xff1a;x86_64&#xff08;amd64&#xff09;操作系统&#xff1a;CentOS 7.8 2003数据库版本&#xff08;含CSDK&#xff09;&#xff1a;GBase 8s V8.8 3.0.0_1 为什么使用QT 5.12.10&#xff1f;该版本包含QODBC。 1&#…

二进制数间按位逻辑运算按位逻辑与、逻辑或运算bitwise_and()bitwise_or()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 二进制数间按位逻辑运算 按位逻辑与、逻辑或运算 bitwise_and() bitwise_or() [太阳]选择题 下列代码最后一次输出的结果是&#xff1f; import numpy as np a, b 3, 8 print("…

Diffusion Models for Image Restoration and Enhancement – A Comprehensive Survey

图像恢复与增强的扩散模型综述 论文链接&#xff1a;https://arxiv.org/abs/2308.09388 项目地址&#xff1a;https://github.com/lixinustc/Awesome-diffusion-model-for-image-processing/ Abstract 图像恢复(IR)一直是低水平视觉领域不可或缺的一项具有挑战性的任务&…

【golang】for语句和switch语句

使用携带range子句的for语句时需要注意哪些细节&#xff1f; numbers1 : []int{1, 2, 3, 4, 5, 6} for i : range numbers1 {if i 3 {numbers1[i] | i} } fmt.Println(numbers1)这段代码执行后会打印出什么内容&#xff1f; 答案&#xff1a;[1 2 3 7 5 6] 当for语句被执行…

C++避坑——most vexing parse问题

1."坑"的问题是什么&#xff1f; 先看一段代码&#xff1a; class Functor { public:void operator()(){std::cout << "我是线程的初始函数" << std::endl;} };int main() {std::thread t(Functor());// 强制高速编译器这是一个构造函数!t.j…

智慧课堂学生行为检测评估算法

智慧课堂学生行为检测评估算法通过yolov5系列图像识别和行为分析&#xff0c;智慧课堂学生行为检测评估算法评估学生的表情、是否交头接耳行为、课堂参与度以及互动质量&#xff0c;并提供相应的反馈和建议。智慧课堂学生行为检测评估算法能够实时监测学生的上课行为&#xff0…

小程序中的全局配置以及常用的配置项(window,tabBar)

全局配置文件和常用的配置项 app.json: pages:是一个数组&#xff0c;用于记录当前小程序所有页面的存放路径&#xff0c;可以通过它来创建页面 window:全局设置小程序窗口的外观(导航栏&#xff0c;背景&#xff0c;页面的主体) tabBar:设置小程序底部的 tabBar效果 style:是否…

java.8 - java -overrideoverload 重写和重载

重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变&#xff0c;核心重写&#xff01; 重写的好处在于子类可以根据需要&#xff0c;定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。 重写方法不…