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

设计原则

    • 研究 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.mzph.cn/news/816000.shtml

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

相关文章

快速寻找可以构建出网通信隧道的计算机

点击星标,即时接收最新推文 本文选自《内网安全攻防:红队之路》 扫描二维码五折购书 为加强内网的安全防范,安全管理员往往会限制内网计算机访问互联网,当然不同机构的限制策略是不一样的,有的完全阻断了内网计算机访问…

如何发布自己的Python库?

Python包发布 1、背景概述2、操作指南 1、背景概述 为什么我们要发布自己的Python库?如果你想让你的Python代码,通过pip install xxx的方式供所有人下载,那就需要将代码上传到PyPi上,这样才能让所有人使用 那么,如何发…

群晖双硬盘实时备份(WebDAV Server+Cloud Sync)

安装和设置 WebDAV Server WebDAV 是一种基于HTTP的协议扩展,它允许用户在远程Web服务器上进行文档的编辑和管理,就如同这些文件存储在本地计算机上一样。使用WebDAV,用户可以创建、移动、复制和修改文件和文件夹。 安装和设置 Cloud Sync…

使用 Prometheus 在 KubeSphere 上监控 KubeEdge 边缘节点(Jetson) CPU、GPU 状态

作者:朱亚光,之江实验室工程师,云原生/开源爱好者。 KubeSphere 边缘节点的可观测性 在边缘计算场景下,KubeSphere 基于 KubeEdge 实现应用与工作负载在云端与边缘节点的统一分发与管理,解决在海量边、端设备上完成应…

地球上四大洋介绍

地球上四大洋的分布是: 太平洋:太平洋是世界上最大的海洋,覆盖了约三分之一的地球表面。它位于亚洲、澳大利亚、美洲和南极洲之间。太平洋的面积约为1.6亿平方公里,拥有世界上最深的点——马里亚纳海沟。 大西洋:大西…

2024HW --> 安全产品 Powershell无文件落地攻击

在HW中,除了了解中间件,web漏洞,这些攻击的手法,还得了解应急响应,安全产品,入侵排查,溯源反制...... 那么今天,就来说一下安全产品(安全公司我就不说了,这个…

001vscode为什么设置不了中文?

VSCode中文插件安装 在VSCode中设置中文的首要步骤是安装“Chinese (Simplified) Language Pack for Visual Studio Code”扩展插件。这一过程十分简单,只需打开VSCode,进入扩展市场,搜索“ Chinese (Simplified) Language Pack ”然后点击…

【MATLAB源码-第49期】基于蚁群算法(ACO)算法的栅格路径规划,输出最佳路径图和算法收敛曲线图。

操作环境: MATLAB 2022a 1、算法描述 蚁群算法是一种模拟自然界蚂蚁觅食行为的启发式优化算法。在蚁群系统中,通过模拟蚂蚁之间通过信息素沟通的方式来寻找最短路径。 在栅格路径规划中,蚁群算法的基本步骤如下: 1. 初始化: …

MES实施优势有哪些?MES制造执行系统的主要内容

各个行业之间也开始进入到了激烈的竞争当中,很多企业为了能够有效提升企业竞争力,都会通过提升自身实力的方式来提升竞争力。一些制造业也会在经营过程当中使用到MES系统,那么,mes系统的优势有哪些呢? 1、优化企业现场…

mysql dump导出导入数据

前言 mysqldump是MySQL数据库中一个非常有用的命令行工具,用于备份和还原数据库。它可以将整个数据库或者特定的表导出为一个SQL文件,以便在需要时进行恢复或迁移。 使用mysqldump可以执行以下操作: 备份数据库:可以使用mysqld…

ELK日志分析系统+Filebeat

目录 一、Filebeat介绍 1、Filebeat简介 2、Filebeat的工作方式 3、filebeat工作流程 4、Filebeat的作用 5、filebeat的用途 1.为什么要用filebeat来收集日志?为什么不直接用logstash收集日志? 2.filebeat和logstash的区别 二、部署(ELFK)Fileb…

自动化测试Junit

1.什么是Junit JUint是Java编程语言的单元测试框架,用于编写和运行可重复的自动化测试。 JUnit 促进了“先测试后编码”TDD的理念,强调建立测试数据的一段代码,可以先测试,然后再应用。这个方法就好比“测试一点,编码一…

【SERVERLESS】AWS Lambda上实操

通过Serverless的发展历程及带给我们的挑战,引出我们改如何改变思路,化繁为简,趋利避害,更好的利用其优势,来释放企业效能,为创造带来无限可能。 一 Serverless概述 无服务器计算近年来与云原生计算都是在…

OSPF星型拓扑和MGRE全连

一,拓扑 二,要求 1,R6为ISP只能配置IP地址,R1-R5的环回为私有网段 2,R1/4/5为全连的MGRE结构,R1/2/3为星型的拓扑结构, 3,R1为中心站点所有私有网段可以互相通讯,私有网段…

antd+vue——datepicker日期控件——禁用日期功能

需求&#xff1a;今天之前的日期禁用 <a-date-pickerv-model.trim"formNE.deliveryTime":disabled-date"disabledDate"valueFormat"YYYY-MM-DD"allowClearstyle"width: 100%" />禁用日期的范围&#xff1a; //时间范围 disab…

第14届java A组蓝桥杯做题记录

A题 特殊日期 package Java14省赛.Java研究生组;import java.time.Year; //特殊判断一下2月份&#xff0c;leaf 为true 1 import java.util.*;import 蓝桥杯.dfs_n皇后; public class 特殊日期 {static int sum(int d){int res 0;while(d > 0){res d % 10;d / 10;}return…

Java GC了解

Jstack找到线程的快照 jvm提供其他命令作用 jps&#xff1a; 虚拟机进程状况工具&#xff0c;类似linux的ps命令 jstat&#xff1a;虚拟机统计信息监视工具&#xff0c;经常看gc情况的会使用到 jinfo: java配置信息工具 jmap&#xff1a; java内存映射工具&#xff0c;dump&am…

微服务篇面试题

1、SpringCloud的组件有哪些&#xff1f; 2、负载均衡如何实现&#xff1f; 3、什么是服务雪崩&#xff1f;怎么解决&#xff1f; 4、项目中有没有做过限流&#xff1f; Tomcat单体可以&#xff0c;分布式不适合 5、解释一下CAP和BASE P&#xff1a;加入node03这边的网络断了&a…

基于PCIe的智能处理系统研究

引言 人工智能是集合众多方向的综合性学科,在诸多应用领域均取得了显著成果。随着航空领域人工智能技术研究的不断深入,面向开放式机载智能交互场景,人工智能的应用可解决诸多问题。例如智能感知、辅助决策等,可利用人工智能算法对多源传感器捕获的海量信息进行快速处理,仅将处…

【8086汇编】汇编语言基础入门

文章目录 一、汇编简介1. 汇编语言的组成2. CPU、寄存器、内存3. CPU对存储器的读写4. 拓展5. 检测6. 解析 二、寄存器1. mov、add命令2. 物理地址3. CS:IP 装段地址和偏移地址3.1 如何改变CS:IP的值 4. 数据段DS:[address]4.1 前置知识&#xff1a;字与字节4.2 DS:[address] 5…