最近没事再次翻开《敏捷软件开发:原则、模式与实践》看,发现以前似懂非懂的东西突然就看懂了,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不仅仅是依赖关系的倒置,它也是接口所有权的倒置。客户拥有接口所有权,而它们的服务者则从这些接口派生。

由客户模块或者层来声明它们所需要的服务接口,那么仅当客户需要时才会对接口改变。这样改变实现抽象接口的类就不会影响到客户。

层次化:

所有结构良好的面向对象架构都具有清晰的层次定义,每个层次通过定义一个良好的、受控的接口向外提供了一组内聚的服务。

面象对象的程序设计倒置了依赖关系,使得细节和策略依赖于抽象,并且常常是客户拥有服务接口。依赖关系的倒置正是好的面向对象设计的标志所在。是实现许多面向对象技术所宣称的好处的基本低层机制。它的正确应用对于创建重用的框架来说是必需的。同时它对于构建在变化面前富有弹性也是重要的。由于抽象和细节彼此隔离,所以代码也非常容易维护。

相关阅读

SOLDI原则之DIP:依赖倒置原则

一文get到SOLID原则的重点的更多相关文章

  1. 超易懂!原来SOLID原则要这么理解!

    说到 SOLID 原则,相信有过几年工作经验的朋友都有个大概印象,但就是不知道它具体是什么.甚至有些工作了十几年的朋友,它们对 SOLID 原则的理解也停留在表面.今天我们就来聊聊 SOLID 原则以 ...

  2. 浅谈 SOLID 原则的具体使用

    SOLID 是面向对象设计5大重要原则的首字母缩写,当我们设计类和模块时,遵守 SOLID 原则可以让软件更加健壮和稳定.那么,什么是 SOLID 原则呢?本篇文章我将谈谈 SOLID 原则在软件开发 ...

  3. 【转】面向对象设计的SOLID原则

    S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写. SRP The Single Responsibility ...

  4. 面向对象设计的SOLID原则

    S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写. SRP The Single Responsibility ...

  5. SOLID 原则

     世纪的前几年里,“ Uncle Bob”Robert Martin 引入了用OOP 开发软件的五条原 则,其目的是设计出更易于维护的高质量系统.无论是设计新应用程序,还是重构现有基 本代码,这些 S ...

  6. 面向对象涉及SOLID原则

    S = Single Responsibility Principle 单一职责原则 O = Opened Closed Principle 开放闭合原则  L = Liscov Substituti ...

  7. TypeScript 中的 SOLID 原则

    下面的文章解释了正确使用 TypeScrip的 SOLID原则. 原文地址:https://samueleresca.net/2016/08/solid-principles-using-typesc ...

  8. 类设计的SOLID原则

    SOLID原则是面向对象范式的核心 单一职责原则(Single Responsible Principle, SRP):对于一个类,应该仅有一个引起它变化的原因.其基础是内聚,表示类完成单一功能的程度 ...

  9. 面向对象的SOLID原则白话篇

    面向对象的SOLID原则 简介 缩写 全称 中文 S The Single Responsibility Principle 单一责任原则 O The Open Closed Principle 开放 ...

随机推荐

  1. PicCompress —— 一款精简的图片压缩工具

    PicCompress 说明 之前上传博客图片过大不方便加载,还有一些微信平台的图片无法上传有大小限制,于是就打算开发个压缩图片的工具 支持图片格式 PNG(.png) JPEG(.jpg, .jpe ...

  2. Fabric2.2中的Raft共识模块源码分析

    引言 Hyperledger Fabric是当前比较流行的一种联盟链系统,它隶属于Linux基金会在2015年创建的超级账本项目且是这个项目最重要的一个子项目.目前,与Hyperledger的另外几个 ...

  3. 开发中常用的Hook

    开发中常用的Hook 什么是Hook? Hook 是一些可以让你在函数组件里"钩入" React state 及生命周期等特性的函数,用来实现一些 class 组件的特性的. 1 ...

  4. Spring Authorization Server授权服务器入门

    11月8日Spring官方已经强烈建议使用Spring Authorization Server替换已经过时的Spring Security OAuth2.0,距离Spring Security OA ...

  5. 2021.11.14 CF1583E Moment of Bloom(LCA+图上构造)

    2021.11.14 CF1583E Moment of Bloom(LCA+图上构造) https://www.luogu.com.cn/problem/CF1583E 题意: She does h ...

  6. 公私钥 SSH 数字证书

    公私钥 SSH 数字证书 小菜鸟今天买了华为云一台服务器,在使用公私钥远程登录服务器的时候,忘记了相关公钥私钥的原理和一些应用了,今天复习一波做个记录. 相关概念 公钥:公钥用来给数据加密,用公钥加密 ...

  7. Ubuntu 下 Mariadb 数据库的安装和目录迁移

    Ubuntu 下 Mariadb 数据库的安装和目录迁移 1.简介 本文主要是 Ubuntu 下 Mariadb 数据库的安装和目录迁移,同样适用于 Debian 系统:Ubuntu 20.0.4 M ...

  8. 【虚拟机】VMware-VMware Tool安装

    1.安装 在VMware Workstation主界面点击菜单"虚拟机".会弹出提示框,点击是. 保持网络状态,等待后台下载,下载后会出现一个压缩包(如果没有出现压缩包请点击这里查 ...

  9. .Net中字符串不变性与相等判断的特殊场景

    今天写bug的时候帮同事解决了一个有趣的问题,可能很多人都会答错.分享给大家. 问题 请看以下例子,并回答问题. var s1 = "12"; var s2 = "12& ...

  10. C# 滑动验证码|拼图验证|SlideCaptcha

    使用背景: 关于滑动验证码的使用场所还是非常多的,如: 调取短信接口之前,和 注册请求之前 或者 频繁会调用的接口 都需要加这个拼图验证.这里先上一下效果图吧(心中无码,自然高清). 话不多说,开撸! ...