一文get到SOLID原则的重点
最近没事再次翻开《敏捷软件开发:原则、模式与实践》看,发现以前似懂非懂的东西突然就看懂了,get到了讲的重点。
SOLID(单一职责原则、开放—封闭原则、里氏替换原则、接口隔离原则以及依赖倒置原则)是由罗伯特·C·马丁引入,成为了面向对象设计中的五个基本原则。当这些原则被一起应用时,它们使得一个程序员开发一个容易进行软件维护和扩展的系统变成可能。
1 单一职责原则(SRP)
定义:一个类应该只有一个发生变化的原因
为何把这两个职责分离到分离到单独的类中很重要呢?因为每一个职责都是变化的一个轴线。当需求变化时,该变化会反映为类的职责变化。如果一个类承担了多于一个的职责,那么引起它变化的原因就会有多个。如果一个类承担的职责过多,就等于把职责耦合在了一起。一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意向不到的破坏。
在SRP中,我们把职责定义为变化的原因,如果你能够想到多于一个的动机去改变一个类,这个类就具有多于一个的职责。有时,我们很难注意到这一点。我们习惯于以组的形式去考虑职责。
仅当变化发生时,变化的轴线才具有实际意义。如果没有征兆,那么应用SRP或者任何其他原则都是不明智的。
软件设计真正要做的许多工作,就是发现职责并把那些职责相互分离。其余原则都会以这样或者那样的方式回到这个问题上。
2 开放封闭原则(OCP)
定义:软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改。
如果程序中的一处改动就会产生连锁反应,导致一系列相关模块的改动,那么设计就具有僵化性的臭味。OCP建议我们应该对系统进行重构,这样以后对系统再进行那样的改动时,就不会导致更多的修改。如果正确地应用OCP,那么以后进行同样的改动时,就只需要添加新的代码,而不必改动已经正常运行的代码。
怎样可能在不改动模块源代码的情况下去更改它的行为呢?如果不更改一个模块,又怎么能够去更改它的功能呢?答案就是抽象。
策略模式(STARTEGY)和模板方法(TEMPLATE METHOD)模式是满足OCP最常用的方法。应用它们,可以把一个功能的通用部分和实现细节部分清晰的分离开来。
在许多方面,OCP都是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处:灵活性、可重用性、以及可维护性。开发人员应该仅仅对程序中呈现出频繁变化的那些部分做出抽象。拒绝不成熟的抽象和抽象本身一样重要。
3 里氏替换原则(LSP)
定义:子类型必须能够替换掉它们的基类型。
LSP得出一个非常重要的结论:一个模型如果孤立的看,并不具有真正意义的有效性。模型的有效性只能通过它的客户程序来表现。
LSP基于契约的设计(Design By Contract,DBC)。使用DBC类的编写者显示地规定针对该类的契约。客户代码的编写者可以通过该契约获悉可以依赖的行为方式。契约是通过为每个方法声明前置条件和后置条件来指定的。要使一个方法得以执行,前置条件要为真。执行完毕后,该方法的后置条件为真。派生类的行为方式和输出不能违反基类已经确立的任务限制,基类的用户不应该被派生类的输出扰乱。
OCP是OOD(面向对象设计)中很多说法的核心。如果这个原则应用得有效,应用程序就会具有更强的可维护性、可重用性以及健壮性。LSP是使OCP成为可能的主要原则之一。正是子类型的可替换性才使得使用基类型表示的模块在无需修改的情况下可以扩展。这种可替换性必须是开发人员可以隐式依赖的。这样如果没有在代码中显式地支持基类型的契约,那么就必须很好地、广泛地理解这些契约。子类型正确的定义是可替换的,可替换性通过隐式或者显式的契约来定义。
4 接口隔离原则(ISP)
定义:不应该强迫客户程序依赖并未使用的方法。
这个原则用来处理“胖”接口所存在的缺点。如果类的接口不是内聚(内聚(Cohesion)是一个模块内部各成分之间相关联程度的度量)的,就表示该类具有“胖”接口。
如果强迫客户程序依赖那些不使用的方法,那么这些客户程序就面临着由于这些未使用的方法的改变所带来的变更。这无意中导致了所有客户程序之间的耦合。换言之,如果一个客户程序依赖于一个含有它不使用的方法的类,但是其他客户却确实要用这个方法,那么当其实客户要求这个类改变时,就会影响到这个客户程序。分离客户就是分离接口。
客户程序应该仅仅以来于它们实际调用的方法。通过把胖类接口分解为多个特定于客户程序的接口,可以实现这个目标。每个特定于客户程序的接口仅仅声明它的特定客户或者客户组调用的那些函数。接着,该胖类就可以继承所有特定于客户程序的接口,并实现它们,这就解除了客户程序和没有调用的方法间的依赖关系,并使客户程序之间互不依赖。
5 依赖倒置原则(DIP)
定义:
a.高层模块不应该依赖于低层模块。二者都应该依赖于抽象。
b.抽象不应该依赖于细节。细节应该依赖于抽象。
该原则是框架设计的核心原则。
倒置的含义
为什么使用"倒置”,倒置是较于传统的软件开发,比如结构化分析和设计,总是倾向于创建一些高层模块依赖于低层模块、策略依赖于细节的软件结构。一个设计良好的面向对象的程序,其依赖程序结构相对于传统的过程式方法设计的通常结构而言就是被“倒置"了。
倒置的是什么?
DIP不仅仅是依赖关系的倒置,它也是接口所有权的倒置。客户拥有接口所有权,而它们的服务者则从这些接口派生。
由客户模块或者层来声明它们所需要的服务接口,那么仅当客户需要时才会对接口改变。这样改变实现抽象接口的类就不会影响到客户。
层次化:
所有结构良好的面向对象架构都具有清晰的层次定义,每个层次通过定义一个良好的、受控的接口向外提供了一组内聚的服务。
面象对象的程序设计倒置了依赖关系,使得细节和策略依赖于抽象,并且常常是客户拥有服务接口。依赖关系的倒置正是好的面向对象设计的标志所在。是实现许多面向对象技术所宣称的好处的基本低层机制。它的正确应用对于创建重用的框架来说是必需的。同时它对于构建在变化面前富有弹性也是重要的。由于抽象和细节彼此隔离,所以代码也非常容易维护。
相关阅读
一文get到SOLID原则的重点的更多相关文章
- 超易懂!原来SOLID原则要这么理解!
说到 SOLID 原则,相信有过几年工作经验的朋友都有个大概印象,但就是不知道它具体是什么.甚至有些工作了十几年的朋友,它们对 SOLID 原则的理解也停留在表面.今天我们就来聊聊 SOLID 原则以 ...
- 浅谈 SOLID 原则的具体使用
SOLID 是面向对象设计5大重要原则的首字母缩写,当我们设计类和模块时,遵守 SOLID 原则可以让软件更加健壮和稳定.那么,什么是 SOLID 原则呢?本篇文章我将谈谈 SOLID 原则在软件开发 ...
- 【转】面向对象设计的SOLID原则
S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写. SRP The Single Responsibility ...
- 面向对象设计的SOLID原则
S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写. SRP The Single Responsibility ...
- SOLID 原则
世纪的前几年里,“ Uncle Bob”Robert Martin 引入了用OOP 开发软件的五条原 则,其目的是设计出更易于维护的高质量系统.无论是设计新应用程序,还是重构现有基 本代码,这些 S ...
- 面向对象涉及SOLID原则
S = Single Responsibility Principle 单一职责原则 O = Opened Closed Principle 开放闭合原则 L = Liscov Substituti ...
- TypeScript 中的 SOLID 原则
下面的文章解释了正确使用 TypeScrip的 SOLID原则. 原文地址:https://samueleresca.net/2016/08/solid-principles-using-typesc ...
- 类设计的SOLID原则
SOLID原则是面向对象范式的核心 单一职责原则(Single Responsible Principle, SRP):对于一个类,应该仅有一个引起它变化的原因.其基础是内聚,表示类完成单一功能的程度 ...
- 面向对象的SOLID原则白话篇
面向对象的SOLID原则 简介 缩写 全称 中文 S The Single Responsibility Principle 单一责任原则 O The Open Closed Principle 开放 ...
随机推荐
- centos6的yum源更新版本
概述 centos6系统从2020年12月1号开始不再维护,官方的yum源不再可用,同时国内的阿里云镜像和163镜像也都不再可用. 但是我们有一些老的服务器仍然在使用centos6系统版本,依赖库的安 ...
- 在keil中加入DSP库并且使用arm_math.h
如果不开启硬件FPU,代码设置和编译控制建议二选一,否则会出现宏定义重复定义的报错
- SQLite 数据库使用记录
SQLite 数据库使用记录 官网 https://www.sqlite.org/index.html 下载地址 https://www.sqlite.org/download.html 参考资料 S ...
- js刷新页面window.location.reload()
window.location.reload()刷新当前页面 window.parent.location.reload()刷新父亲对象(用于框架) opener.location.reload()刷 ...
- NodeJs学习日报day8——接口编写
今天看了黑马NodeJs中关于接口编写以及跨域问题的视频
- [源码解析] TensorFlow 之 分布式变量
[源码解析] TensorFlow 之 分布式变量 目录 [源码解析] TensorFlow 之 分布式变量 1. MirroredVariable 1.1 定义 1.2 相关类 1.2.1 类体系 ...
- 2021.08.10 Euler函数总结
2021.08.10 Euler函数总结 知识: 记 φ(n) 表示在 [1,n] 中与 n互质的数的个数. 1.p为质数,则 \[φ(p^l)=p^l-p=p^{l-1}(p-1) \] 注:每p个 ...
- 24张图攻克border-image
大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...
- zookeeper篇-watch命令
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 每个路径节点都有一个watcher监控,当该节点数据改变时(CRUD), ...
- netty系列之:netty中的自动解码器ReplayingDecoder
目录 简介 ByteToMessageDecoder可能遇到的问题 ReplayingDecoder的实现原理 总结 简介 netty提供了一个从ByteBuf到用户自定义的message的解码器叫做 ...