SRC单一职责原则
一、定义
一个类应该只有一个发生变化的原因。
二、为什么要使用SRC
因为每一个职责都是变化的一个轴线。当需求变化时,这种变化就会反映为类的职责的变化。如果一个类承担了多于一个的职责,那么引起它变化的原因就会有多个。
如果一个类承担的职责过多,就等于把这些职责耦合在了一起。一个职责的变化可能会消弱或抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭到意想不到的破坏。
三、案例演示
考虑图中的设计。

Rectangle类具有两个方法,一个方法把矩形绘制到屏幕上,另一个方法则是计算矩形的面积。 现在有两个应用程序使用Rectangle类。一个是利用Rectangle计算矩形面积,但不需要绘制矩形;另一个应用程序可能会绘制矩形,也可能计算面积。
这个设计违反了单一职责原则。Rectangle类具有两个职责。第一个职责提供了矩形面积的计算;第二个职责提供了矩形绘制。 对于SRC的违反导致了一些严重的问题。
对于这个违反了SRC的程序有以下几点问题:
首先,我们必须在左侧的程序中包含进GUI代码,即使我们是不需要的。
其次,如果右侧程序的改变导致了Rectangle的改变,那么这个改变会迫使我们重新构建、测试和部署左侧的程序。
一个较好的设计就是把这两个职责分离到如下图所示的两个完全不同的类中。这个设计把Rectangle类中进行计算的部分移到了GeometricRectangle类中。现在矩形绘制方法的变化不会影响到左侧的程序。

四、什么是职责
在SRC中,我们把职责定义为变化的原因。
如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。
有时,我们很难注意到这一点,我们习惯于以组的形式去考虑职责。 例如,下面的Modem接口,大多数人认为这个接口非常合理。该接口所声明的4个方法确实是调制解调器所具有的功能 。
public interface Modem
{
public void Dial(string pno); //连接
public void Hangup(); //断开
public void Send(char c); //发送
public char Recv(); //接收
}
然而,该接口中却显示出两个职责。第一个职责是连接管理;第二个职责是数据通信。
这两个职责需要分开吗?
这依赖于应用程序变化的方式。如果应用程序的变化会影响到连接管理方法的签名,那么这个设计就具有僵化性,因为调用send和recv的类必须重新编译、部署。在这种情况下,这两个职责应该被分离,如下图所示。

另一方面,如果应用程序的变化方式总是导致这两个职责同时变化,那就不必分离它们。
记住这么一个结论,仅当变化发生时,变化的轴线才具有实际意义。如果没有征兆,那么应用SRP或者任何其它原则都是不明智的。
五、分离耦合的职责
请注意,在上图中,把两个职责都耦合进了ModemImplementation类中。这也许不是最好的,但是或许必须得这么做。常常会有一些和硬件或者操作系统的细节有关的原因,迫使我们把不愿意耦合在一起的东西耦合在了一起。然而,对于应用的其余部分来说,通过分离它们的接口我们已经解耦了。
六、持久化
下图展示了一种常见的违反SRP的情形。

Employee类包含了业务规则和对于持久化的控制。这个两个职责在大多数情况下绝不应该混合在一起。业务规则往往会频繁地变化,而持久化的方式却不会如此频繁的变化,并且变化的原因也是完全不同的,它们实在两个方向上变化,一个是业务方向上变化,另一个是持久化方向上变化。
把业务规则和持久化子系统绑定在一起的做法是自讨苦吃。 测试驱动的开发实践常常会远在设计出现臭味之前就迫使我们分离这两个职责。然而,如果测试没有迫使这种分离,那么就应该使用Facade(外观)、DAO(数据访问)或者Proxy(代理)模式对设计进行重构,分离这两个职责。
七、结论
SRP是所有原则中最简单的原则之一,也是最难正确运用的原则之一。我们会不自觉地把职责结合到一起。软件设计真正要做的许多工作,就是发现职责并把那些职责相互分离。
SRC单一职责原则的更多相关文章
- C#设计模式系列:单一职责原则(Single Responsibility Principle)
1.单一职责原则的核心思想 一个类应该有且只有一个变化的原因. 2.为什么要引入单一职责原则 单一职责原则将不同的职责分离到单独的类,每一个职责都是一个变化的中心.当需求变化时,这个变化将通过更改职责 ...
- C#软件设计——小话设计模式原则之:单一职责原则SRP
前言:上篇C#软件设计——小话设计模式原则之:依赖倒置原则DIP简单介绍了下依赖倒置的由来以及使用,中间插了两篇WebApi的文章,这篇还是回归正题,继续来写写设计模式另一个重要的原则:单一职责原则. ...
- 单一职责原则(Single Responsibility Principle)
单一职责原则(SRP:The Single Responsibility Principle) 一个类应该有且只有一个变化的原因. There should never be more than on ...
- 开放-封闭原则(OCP)开-闭原则 和 依赖倒转原则,单一职责原则
单一职责原则 1.单一职责原则(SRP),就一个类而言,应该仅有一个引起它变化的原因 2.如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会消弱或抑制这个类完成其他职责的能力. ...
- 敏捷软件开发:原则、模式与实践——第8章 SRP:单一职责原则
第8章 SRP:单一职责原则 一个类应该只有一个发生变化的原因. 8.1 定义职责 在SRP中我们把职责定义为变化的原因.如果你想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责.同时,我 ...
- 第2章 面向对象的设计原则(SOLID):1_单一职责原则(SRP)
1. 单一职责原则(Single Responsibility Principle,SRP) 1.1 单一职责的定义 (1)定义:一个类应该仅有一个引起它变化的原因.这里变化的原因就是所说的“职责”. ...
- 1.单一职责原则(Single Responsibility Principle)
1.定义 就一个类而言,应该仅有一个引起它变化的原因. 2.定义解读 这是六大原则中最简单的一种,通俗点说,就是不存在多个原因使得一个类发生变化,也就是一个类只负责一种职责的工作. 3.优点 类的复杂 ...
- 【设计模式六大原则1】单一职责原则(Single Responsibility Principle)
http://blog.csdn.net/zhengzhb/article/category/926691/1 图片素材来源,java学习手册 ps.内容为自己整理 定义:不要存在多于一个 ...
- [设计模式]<<设计模式之禅>>之关于单一职责原则
单一职责原则的英文名称是Single Responsibility Principle,简称是SRP. 这个原则存在争议之处在哪里呢?就是对职责的定义,什么是类的职责,以及怎么划分类的职责.我们先举个 ...
随机推荐
- webservice5
如何访问webservice . 三种方式我知道, 但是, 方式1 只说明了如何访问wsdl, 不知道如何调用,现在就是需要知道如何像下面url描述一样 , http get .post 方式调用ws ...
- Java中main()的args的知识点浅谈
我们先来了解下Java中main()方法的默认定义格式: public static void main(String[] args){ }1.main方法是程序执行的入口,除了args这个形参变量可 ...
- Logstash为什么那么慢?—— json序列化
今天跟峡谷金桥聊天,询问起Logstash的性能,金桥提示说Logstash中json的序列化是浪费性能的一方面.于是便有了下面的测试: 第一步,造数据 首先需要造一份数据,数据可以通过logstas ...
- SSH+JPA查询两个数据库
1.第一步导包: 1.struts2包: 2.spring包: 3.hibernate包: 4.数据库包: 2.web.xml配置 3.struts2的配置: 1.struts.xml 2.s001. ...
- 从双十一战报看传统大家电如何O2O转型?
说到大家电电商,大家都会想起天猫.京东.苏宁易购.国美在线等各大电商平台,他们这一次的双十一又实现了较大规模的增长,而各大电商平台家电辉煌战绩的背后实际上是各大品牌家电的成功. 格力今年双十一当天创下 ...
- fir.im Weekly - 你与优秀源码之间只差一个 Star
说起开源社区,Github 是一个不可缺少的存在.作为全球最大的同性交友网站,上面有太多优秀的开源代码库和编程大神,让无数开发者心生向往.那么如何正确的使用 Github,也许是编程学习之必要.来看下 ...
- KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
if绑定目的 if绑定一般是格式是data-bind=if:attribute,if后所跟属性或表达式的值应为bool值(也可以是非bool值,当非空字符串时则为真),if绑定的作用与visible绑 ...
- python的继承
继承是面向对象的重要特征之一,继承是两个类或者多个类之间的父子关系,子进程继承了父进程的所有公有实例变量和方法.继承实现了代码的重用.重用已经存在的数据和行为,减少代码的重新编写,python在类名后 ...
- IO流-文件管理
File f = new File(“test.txt”); File的构造器不会在文件不存在的情况下新建一个文件,从File对象中创建文件是由文件流的构造器或File类的createNewFile方 ...
- 总结整理 -- python系列
python系列 python--基础学习(一)开发环境搭建,体验HelloWorld python--基础学习(二)判断 .循环.定义函数.继承.调用 python--基础学习(三)字符串单引号.双 ...