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

news2024/11/22 16:32:11

设计原则

    • 研究 23 种设计模式是困难的,甚至是没必要的
    • 六大设计原则
      • 零、单一职责原则
      • 开闭原则
      • 里氏代换原则
      • 依赖倒置原则
      • 接口隔离原则
      • 迪米特法则
      • 合成复用原则

研究 23 种设计模式是困难的,甚至是没必要的

设计模式有23种,我认为对普通人来说想要灵活掌握这23种设计模式是十分困难的。

  1. 设计模式的书中,介绍每一种设计模式,往往都举一个形象有趣的例子,然后读者会被有趣的例子和实现所吸引,而其背后蕴含的道理往往很难通过简单的思考来想清楚。
  2. 意识到上一点的人,通过简单思考后,觉得23种设计模式就像23种模板。23 这个数字已经足够大,大到背会这23个模板都是一个比较大的工程量。于是,学习者会转向记忆这23中模板上,并且最后以记不住这些模板告终。

首先,记忆模板很重要。学习的本质就是:记忆 + 思维。但是记忆哪些东西才是最关键的。记住那些关键假设,推理出进一步的结论。如果再次迭代,记住下一步结论,就能推理出下一步的结论。学习就是这样循环往复。
因此,只记忆模板,不求甚解是学习的大忌。

设计模式难学的第二个难点是思维容易发散,没有统一的思维切入点。光靠 23 种模板,很难让人明白,这种设计比那种设计好在哪里?应该怎样向好的方向去设计软件?23 种设计模式,反而使大脑更发散了。

设计模式底层的底层原理其实是六大设计原则。我认为仔细揣摩这六大原则,使用六大原则来分析23种设计模式的利弊,才是学习设计模式的正途。

软件设计是一个哲学问题。更注重设计的利弊思辨,而不是一个固定的答案。而大多数人包括我缺乏这样的思辨能力。六大设计模式,可以辅助我们分析设计的好坏。

六大设计原则,是针对面向对象的设计模式的原则,也就是针对 封装、继承和多态 的使用原则。

  • 零、单一职责原则:这是所有模块设计的原则,确保功能模块化,与面向对象无关。
  • 一、开闭原则:对拓展(继承)开放,对修改关闭
  • 二、里氏替换原则:子类不改变父类原有职责
  • 三、依赖倒置原则 :依赖抽象接口,不依赖具体实现
  • 四、接口隔离原则:拆分大接口
  • 五、迪米特法则 :对别的模块知道的越少越好,最好仅知道少量的接口。
  • 六、合成复用原则:多用组合,少用继承

这六大原则也不是必须遵守的。因为这些原则都是定性的描述,多用xx,少用 xx等等。我们遵循这些模式,需要遵循到什么程度是很难判断的?毕竟现实中都是实在的量,接口有几个参数,我继承了几个类,等等。衡

因此我们要做得是分析利弊:

  1. 如果违背了某一原则,我们要付出什么样的代价
  2. 如果遵循了某一原则,我们得到了什么要的好处

软件设计本身就是一场不同设计目标之间的权衡。抽象程度高,则代码更灵活,但是可读性会变差。高性能,则需要更多缓存。所以我要说的是,如果违背原则的代价可以承受,那就可以违背原则。

事实上,由于软件设计是一个哲学问题,有另外一本书叫 《软件设计的哲学》写的也很不错,其中系统阐述了什么是软件的复杂性。里面的一些观点,貌似还要和这里相反。所以说,哲学是讲辩证法的。

六大设计原则

零、单一职责原则

一个类只能有一个引起它变化的原因。这个原因就是这个类的职责。

但说到底,职责的划分也是设计,把两件事当做一个职责也不是不可能。

如果违背了这一原则,一个类存在两个以上的职责,有以下两点代价

  1. 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;
  2. 当用户仅需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。

所以,如果几个职责的实现不会有太大变化,或者这些职责只在一个地方用的时候,违背这个原则也无碍

开闭原则

对扩展开放,对修改关闭

拓展就是继承。通过继承抽象接口来实现新的功能,而不是修改核心功能代码。

里氏代换原则

任何基类出现的地方,子类一定可以出现。子类可以拓展,但不能改变父类原有的功能。

  • 子类不能覆盖父类的非抽象方法
  • 子类中可以增加自己特有的方法。
  • 确保兼容父类的用法:
    • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
    • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。

依赖倒置原则

依赖抽象,不要依赖实体。加入 A 模块依赖 B 模块,可以选择不要直接依赖 B 模块,而让 A 依赖一个接口IB,然后使用 B 实现一个 IB。从图上看,对 B 的依赖发生了反转
在这里插入图片描述

接口隔离原则

将庞大的接口拆分成小接口,放在不同的模块中去实现。

迪米特法则

最少知道原则。每个模块对于其他单元只能拥有有限的知识。尤其是要依赖接口,而不是依赖具体实现。

合成复用原则

多用合成聚合,少用继承。继承是一个很强的依赖。体现在

  • 对基类的修改会影响所有子类
  • 子类必须实现基类所有的抽象接口
  • 子类被强制拥有了基类的所有内容。因此:
    • 实现子类还需要理解所有基类的其他已实现的接口。否则,你的继承就不成立,因为你不全面了解你的父亲,你就解释不了为什么要继承。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】读取时间判定操作次数问题和一些解决办法

几种类 datetime.striptime() 计算两个字符串之间的时间差 datetime.striptime()计算两个字符串之间的时间差 datatime类提供函数处理日期和时间 Striptime()分析字符串值以固定格式表示时间然后存储为函数参数 输出就是: time.sleep() time模块打印时间按照对…

python--递归算法篇

1、给定一个包含n1个整数的数组nums,其数字在1到n之间(包含1和n), 可知至少存在一个重复的整数,假设只有一个重复的整数,请找出这个重复的数 def repeat(ls:list) -> list:#把个数超过1的数&#xff0c…

AutoCAD 2024 安装注册教程

前言 大家好,我是梁国庆。 本篇分享的安装包是 AutoCAD 的全新版本——AutoCAD 2024,下文安装教程中简称 AutoCAD。 时间:2024年4月8日。 获取 AutoCAD 安装包 我已将本篇所使用的安装包打包上传至百度云,扫描下方二维码关注…

014:vue3 van-list van-pull-refresh实现上拉加载,下拉刷新

文章目录 1. 实现上拉加载,下拉刷新效果2. van-list,van-pull-refresh组件详解2.1 van-list组件2.2 van-pull-refresh组件 3. 完整案例4. 坑点:加载页面会一直调用加载接口 1. 实现上拉加载,下拉刷新效果 通过下拉刷新加载下一页…

DMA的认识

DMA介绍 Q:什么是DMA? DMA( Direct Memory Access,直接存储器访问 ) 提供在 外设与内存 、 存储器和存储器 、 外设 与外设 之间的 高速数据传输 使用。它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU ,在这个时间中&am…

Matlab与ROS(1/2)---Message(三)

0. 简介 消息是ROS中交换数据的主要容器。主题和服务使用消息在节点之间传输数据。为了标识其数据结构,每条消息都有一个消息类型。例如,来自激光扫描仪的传感器数据通常以sensor_msgs/LaserScan类型的消息发送。每种消息类型标识消息中包含的数据元素。…

汽车制造业PMC组态应用最佳实践

01案例及行业介绍 汽车制造工业是我国国民经济的重要支柱产业,汽车制造工厂一般包含冲压、焊装、涂装、总装四大车间。每辆汽车的生产过程被分解成很多加工任务下发给各个车间进行完成。车辆从冲压车间开始到总装车间结束一直进行不同类型的工序加工。 PMC即生产控…

docker 上达梦导入dump文件报错:本地编码:PG GBK,导入女件编码:PGGB18030

解决方案: 第一步进入达梦数据容器内部 docker exec -it fc316f88caff /bin/bash 第二步:在容器中 /opt/dmdbms/bin目录下 执行命令 cd /opt/dmdbms/bin./dimp USERIDSYSDBA/SYSDBA001 FILE/opt/dmdbms/ZFJG_LJ20240407.dmp SCHEMASZFJG_LJUSERIDSYSD…

ChatGPT基础(二) ChatGPT的使用和调优

文章目录 ChatGPT的特性采用关键词进行提问给ChatGPT指定身份提升问答质量的策略1.表述方式上的优化2.用"继续"输出长内容3.营造场景4.由浅入深,提升问题质量5.预设回答框架和风格 ChatGPT的特性 1.能够联系上下文进行回答 ChatGPT回答问题是有上下文的&…

微服务学习 Eureka注册中心

服务调用时候出现问题,当服务者很多时候,比如不同的端口。消费者如何找到服务者的地址?又如何判断服务者是否健康。 Eureka基本原理: 总结:如果有多个服务提供者,消费者该如何选择? 搭建Eureka注册中心: 1.…

django基于python的法院执法案件管理系统

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行,将系统所使用到的表以及数据存储到MySQL数据库中,方便对数据进行操作本课题基于WEB的开发平台,设计的基本思路是: 框架:django/flask 后端&#xff…

【YOLOv9改进[损失函数]】使用MPDIou回归损失函数帮助YOLOv9模型更优秀

本文中,第一部分概述了各种回归损失函数,当然也包括了今天的主角MPDIou。第二部分内容为在YOLOv9中使用MPDIou回归损失函数的方法。 1 回归损失函数(Bounding Box Regression Loss) 边界框回归损失计算的方法包括GIoU、DIoU、CI…

纯css实现switch开关

代码比较简单&#xff0c;有需要直接在下边粘贴使用吧~ html: <div class"switch-box"><input id"switch" type"checkbox"><label></label></div> css&#xff1a; .switch-box {position: relative;height: 25px…

全球媒体发稿:海外发稿数字期刊Digital Journal

全球媒体发稿&#xff1a;海外发稿数字期刊Digital Journal ​官网&#xff1a; digitaljournal.com 数字期刊&#xff0c;加拿大知名门户&#xff0c;月访量超过30万。 是一个全球媒体平台和内容合作伙伴&#xff0c;通过捕捉和报道第一&#xff0c;提升新闻周期中的声…

顶顶通呼叫中心中间件-SIP分机安全(mod_cti基于FreeSWITCH)

介绍 运行在公网的FreeSWITCH服务器&#xff0c;每天都会接收到很多恶意的呼叫请求和注册请求&#xff0c;尝试盗打电话。合理的配置可以防止电话给倒打&#xff0c;但是每天大量的攻击&#xff0c;会让FS产生很多日志&#xff0c;降低FreeSWITCH的处理能力&#xff0c;cti模块…

C语言--2048小游戏

需要用到EasyX图形库 #include <stdio.h> #include <stdlib.h> #include <time.h> #include<assert.h> #include <conio.h> #include <windows.h> #include<graphics.h> #include<string.h> #define ROW 4 /* 行数 */ #defin…

K-means和逻辑回归

逻辑回归 一个事件的几率是该事件发生的概率/该事件不发生的概率&#xff1a;P/&#xff08;1-P&#xff09; 对数几率是&#xff1a;log(P/&#xff08;1-P&#xff09;) **考虑对输入x分类的模型&#xff1a;**log(P/&#xff08;1-P&#xff09;)wx 则 Pexp(wx)/(exp(w*x)…

进口PFA容量瓶高纯透明聚四氟乙烯材质耐强酸碱PFA定容瓶

PFA容量瓶&#xff0c;也叫特氟龙容量瓶&#xff0c;是用于配制标准浓度溶液的实验室器皿&#xff0c;是有着细长颈、梨形肚的耐强腐蚀平底塑料瓶&#xff0c;颈上有标线&#xff0c;可直接配置标准溶液和准确稀释溶液以及制备样品溶液。 因其有着不易碎、材质纯净、化学稳定性…

应急响应-战前反制主机HIDSElkeid蜜罐系统HFish

知识点 战前-反制-平台部署其他更多项目&#xff1a; https://github.com/birdhan/SecurityProduct HIDS&#xff1a;主机入侵检测系统&#xff0c;通常会有一个服务器承担服务端角色&#xff0c;其他主机就是客户端角色&#xff0c;客户端加入到服务端的检测范围里&#xff…

ERA拓展之旅:2024香港Web3峰会聚焦全球Web3发展

2024年香港Web3大型峰会是一次令人难忘的体验。这次峰会吸引了来自世界各地的Web3爱好者和从业者齐聚一堂&#xff0c;共同探讨着Web3的未来发展方向与机遇。在这个热情洋溢的氛围中&#xff0c;展现了对Web3的热情&#xff0c;分享彼此的见解和理念&#xff0c;探讨了未来的行…