一、定义

  一个类应该只有一个发生变化的原因。

二、为什么要使用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单一职责原则的更多相关文章

  1. C#设计模式系列:单一职责原则(Single Responsibility Principle)

    1.单一职责原则的核心思想 一个类应该有且只有一个变化的原因. 2.为什么要引入单一职责原则 单一职责原则将不同的职责分离到单独的类,每一个职责都是一个变化的中心.当需求变化时,这个变化将通过更改职责 ...

  2. C#软件设计——小话设计模式原则之:单一职责原则SRP

    前言:上篇C#软件设计——小话设计模式原则之:依赖倒置原则DIP简单介绍了下依赖倒置的由来以及使用,中间插了两篇WebApi的文章,这篇还是回归正题,继续来写写设计模式另一个重要的原则:单一职责原则. ...

  3. 单一职责原则(Single Responsibility Principle)

    单一职责原则(SRP:The Single Responsibility Principle) 一个类应该有且只有一个变化的原因. There should never be more than on ...

  4. 开放-封闭原则(OCP)开-闭原则 和 依赖倒转原则,单一职责原则

    单一职责原则 1.单一职责原则(SRP),就一个类而言,应该仅有一个引起它变化的原因 2.如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会消弱或抑制这个类完成其他职责的能力. ...

  5. 敏捷软件开发:原则、模式与实践——第8章 SRP:单一职责原则

    第8章 SRP:单一职责原则 一个类应该只有一个发生变化的原因. 8.1 定义职责 在SRP中我们把职责定义为变化的原因.如果你想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责.同时,我 ...

  6. 第2章 面向对象的设计原则(SOLID):1_单一职责原则(SRP)

    1. 单一职责原则(Single Responsibility Principle,SRP) 1.1 单一职责的定义 (1)定义:一个类应该仅有一个引起它变化的原因.这里变化的原因就是所说的“职责”. ...

  7. 1.单一职责原则(Single Responsibility Principle)

    1.定义 就一个类而言,应该仅有一个引起它变化的原因. 2.定义解读 这是六大原则中最简单的一种,通俗点说,就是不存在多个原因使得一个类发生变化,也就是一个类只负责一种职责的工作. 3.优点 类的复杂 ...

  8. 【设计模式六大原则1】单一职责原则(Single Responsibility Principle)

        http://blog.csdn.net/zhengzhb/article/category/926691/1 图片素材来源,java学习手册 ps.内容为自己整理   定义:不要存在多于一个 ...

  9. [设计模式]<<设计模式之禅>>之关于单一职责原则

    单一职责原则的英文名称是Single Responsibility Principle,简称是SRP. 这个原则存在争议之处在哪里呢?就是对职责的定义,什么是类的职责,以及怎么划分类的职责.我们先举个 ...

随机推荐

  1. PS 多次剪裁同一图片

    一个图品里面有两个小图,要分别抠出来. 我以前的做法是,先扣一个,重新打开文件,再扣另外一个. 今天发现一个简单的办法,不用重新打开文件. 就是在扣完第一个的时候,打开历史记录面板,双击 打开 动作, ...

  2. 自制C#版3DS文件的解析器并用SharpGL显示3DS模型

    自制C#版3DS文件的解析器并用SharpGL显示3DS模型 我已经重写了3ds解析器,详情在此(http://www.cnblogs.com/bitzhuwei/p/CSharpGL-2-parse ...

  3. Bootstrap~Panel和Table

    回到目录 在我们对一个页面进行设计时,分块是必须的,没有一个网站是一栏而下的,除非你是在看小说,否则你的页面设计一定是分块的,即它由于多个panel组件,在bootstrap里叫到栅格系统,而在每行每 ...

  4. EF架构~通过EF6的DbCommand拦截器来实现数据库读写分离~终结~配置的优化和事务里读写的统一

    回到目录 本讲是通过DbCommand拦截器来实现读写分离的最后一讲,对之前几篇文章做了一个优化,无论是程序可读性还是实用性上都有一个提升,在配置信息这块,去除了字符串方式的拼接,取而代之的是sect ...

  5. Python数据类型之“数字(numerics)”

    上一节内容说的是"Python基本语法",本节主要讲下Python中的数据类型. 存储在内存中的数据通常有两个属性: 在内存中的存放位置:这个存放位置通过变量名可以找到: 在内存中 ...

  6. 使用余弦定理制作磁盘形状h5音乐播放器

    目录 [1]功能实现 [2]效果展示 [3]原理说明 旋转原理 余弦定理 [4]代码实现 HTML CSS JS [5]源码查看 功能实现 [1]歌曲播放进度转换成视觉的旋转角度 [2]点击磁盘任意位 ...

  7. 【目录】Newlife XCode组件相关文章目录

    本博客所有文章分类的总目录链接:本博客博文总目录-实时更新  1.Newlife XCode组件相关文章目录  1.Newlife XCode组件资源目录汇总[2013年版]    2.Newlife ...

  8. timus_1007_代码字

    题目要求:对于所有一个长度为N的字(这些字由0和1组成),在经过一条线路后,这些字可能会做如下的修改: 1. 0可能变成1,但只能发生一次. 2. 0或者1可能被去掉,但也只能发生一次. 3. 0或者 ...

  9. Spark入门实战系列--8.Spark MLlib(下)--机器学习库SparkMLlib实战

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .MLlib实例 1.1 聚类实例 1.1.1 算法说明 聚类(Cluster analys ...

  10. WebStorm 9 自动编译 LESS 产出 CSS 和 source maps

    1.双击桌面Chrome图标,打开Chrome,按键盘“F12”键,打开开发工具界面,点击其右上角的“设置”按钮,勾选“Enable JavaScript source maps”  及“Enable ...