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

设计原则

    • 研究 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.rhkb.cn/news/309073.html

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

相关文章

Windows 关闭占用指定端口的进程

以下示例以443端口为例,具体哪个端口视自己情况而定 输入命令 # 输出的最后一列就是进程号pid netstat -ano | findstr "443" 找出占用443端口的进程号(pid)(第二列是你本机的应用占用的端口,看第二列就行)如下图&am…

音频变速python版

音频变速 如何能在不改变音频其他特点的情况下,只改变语速呢? 有几个python的库可以实现该功能,下面一一介绍。 pydub库 首先,确保安装了pydub和ffmpeg。 下面是一个简单的Python脚本,展示如何改变音频的播放速度&a…

OpenCV4.9​​​​基本阈值操作

目标 在本教程中,您将学习如何: 使用 OpenCV 函数 cv::threshold 执行基本阈值操作 理论依据 注意 下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书 阈值? 最简单的分割方法应用示例:分…

使用 R.swift(生成不了R.generated.swift)

今天算是正儿八经创建第一个swift工程,照着视频引用R.swift pod R.swift 工程配置 "$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/R.generated.swift" $TEMP_DIR/rswift-lastrun $SRCROOT/R.generated.swift * 注意 Run角本要放在 Che…

vmware安装win10及ubuntu

安装win10 新建一个文件夹 选择刚才创建的文件夹 选择需要保存文件的位置,还是选择刚才创建的文件夹 选择自定义硬件 选择下载的win10镜像iso文件,导入后,点击完成即可 接下来就是下一步 没有此电脑,可以点击个性化-》主题-》桌面设置…

已解决ERROR:ssl_client_socket_impl.cc(992)] handshake failed; returned -1, SSL error code 1, net_error

已解决ERROR:ssl_client_socket_impl.cc(992)] handshake failed; returned -1, SSL error code 1, net_error -101 文章目录 报错问题报错翻译报错原因解决方法千人全栈VIP答疑群联系博主帮忙解决报错 报错问题 粉丝群里面的一个小伙伴遇到问题跑来私信我,想用s…

MySQL复习

in和exists的区别? in是内外表hash连接,exists是对外表做loop循环,每次loop后再对内表查询,如果外表小就用exists; not in和not exists前者是全表扫描,后者是可以走索引 锁 对于标准的插入操作&#xf…

CUDA编程---全局内存

CUDA内存模型概述 内存的访问和管理是所有编程语言的重要部分。在现代加速器中,内存管理对高性能计算有着很大的影响。因为多数工作负载被加载和存储数据的速度所限制,所以有大量低延迟、高带宽的内存对性能是十分有利的。 然而,大容量、高性…

基于51单片机的无线病床呼叫系统设计—LCD1602显示

基于51单片机的无线病床呼叫系统 (仿真+程序+原理图+设计报告) 功能介绍 具体功能: 1.病人按下按键,LCD1602显示对应的床位号; 2.多人同时呼叫,显示屏同时显示&#xf…

React 使用 three.js 加载 gltf 3D模型 | three.js 入门

系列文章 React 使用 three.js 加载 gltf 3D模型 | three.js 入门React three.js 3D模型骨骼绑定React three.js 3D模型面部表情控制React three.js 实现人脸动捕与3D模型表情同步结合 react-webcam、three.js 与 electron 实现桌面人脸动捕应用 示例项目(gitcode)&#xf…

开源博客项目Blog .NET Core源码学习(15:App.Hosting项目结构分析-3)

本文学习并分析App.Hosting项目中前台页面的关于本站页面和点点滴滴页面。 关于本站页面 关于本站页面相对而言布局简单,与后台控制器类的交互也不算复杂。整个页面主要使用了layui中的面包屑导航、选项卡、模版、流加载等样式或模块。   面包屑导航。使用layui…

【C++]C/C++的内存管理

这篇博客将会带着大家解决以下几个问题 1. C/C内存分布 2. C语言中动态内存管理方式 3. C中动态内存管理 4. operator new与operator delete函数 5. new和delete的实现原理 6. 定位new表达式(placement-new) 1. C/C内存分布 我们先来看下面的一段代码和相关问题 int global…

第二证券策略:股指预计维持震荡格局 关注汽车、工程机械等板块

第二证券指出,指数自今年2月份阶段低点反弹以来,3月份持续高位整理。进入4月份之后面对年报和一季报的双重财报发表期,预计指数短期保持高位整理概率比较大。前期缺乏成绩支撑的概念股或有回落的危险,主张重视成绩稳定、估值低、分…

快速入门深度学习9.1(用时20min)——GRU

速通《动手学深度学习》9.1 写在最前面九、现代循环神经网络9.1 门控循环单元(GRU)9.1.1. 门控隐状态9.1.1.1. 重置门和更新门9.1.1.2. 候选隐状态9.1.1.3. 隐状态 9.1.3 API简洁实现小结 🌈你好呀!我是 是Yu欸 🌌 20…

HTML图片

图片标签: ~img图片标签 ~是自结束标签 ~属性 ~src表示要引入图片的位置 ~src需要一个路径作为参数 ~alt是对图片的描述 ~帮助搜索引擎来识别图片 ~如果不写alt则搜索引擎不会收录图片 ~width与height只有一个时是同步改变的,但两者同时存在时则是两者按…

头歌-机器学习 第11次实验 softmax回归

第1关:softmax回归原理 任务描述 本关任务:使用Python实现softmax函数。 相关知识 为了完成本关任务,你需要掌握:1.softmax回归原理,2.softmax函数。 softmax回归原理 与逻辑回归一样,softmax回归同样…

MySQL学习笔记(数据类型, DDL, DML, DQL, DCL)

Learning note 1、前言2、数据类型2.1、数值类型2.2、字符串类型2.3、日期类型 3、DDL总览数据库/表切换数据库查看表内容创建数据库/表删除数据库/表添加字段删除字段表的重命名修改字段名(以及对应的数据类型) 4、DML往字段里写入具体内容修改字段内容…

杰发科技AC7840——CAN通信简介(3)_时间戳

0. 时间戳简介 时间戳表示的是收到该CAN消息的时刻,通过连续多帧的时间戳,可以计算出CAN消息的发送周期,也可以用于判断CAN消息是否被持续收到。 1. 使用步骤 注意分别是发送和接收的功能: 2. 现象分析_接收时间戳 看下寄存器的…

机器学习(31)PINN

文章目录 摘要Abstract一、监督学习二、文献阅读1. 题目2. abstract3. 偏微分方程的数据驱动解3.1连续时间模型example(Schrodinger equation): 3.2离散时间模型Example (Allen–Cahn equation): 4. 文献解读4.1 Introduction4.2 创新点 三、实验内容1.实…

Eigen库从入门到放弃(2. Getting Started)

Eigen的头文件定义了多种类型,但是对于简单的来说,使用MatrixXd就足够了,MatrixXd表示任意尺寸的矩阵,但是要注意数据类型是double的。Eigen/Dense的头文件定义了所有MatrixXd和相关类型的成员函数。所有头文件中定义的函数都是在…