单一职责原则

SRP(The Single Responsibility Principle):一个类应该只有一个发生变化的原因。这里的变化指职责的变化。

SRP 很好理解,它的要求是 让一个类只做一种类型责任,当这个类需要承当其他类型的责任的时候,就需要分解这个类。听起来很简单,即一个类指做一种事情。这里是一种并不是一件事情。

若果一个类承担的职责过多,就等于把这些职责耦合在了一起。一个职责的变化可能会削弱或者抑制这个类其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。

打个比方:生产线上的员工在作业时,他们每个人的工作职责都非常明确,只负责某一个环节,只被安排做某一件事情。这个和 SRP 感觉很像。

如何定义职责

SPR 中,我们把职责定义为变化的原因。如果我们能想到对于一个的动机去改变一个类,那么这个类就具有对于一个的职责。不过,通常情况下,我们会更习惯于用组的形式去考虑职责。

若下面的所示的关系型 Database 处理接口:

public interface IRdbmsStorage
{
  IDbConnection Connection(string connectionString);   IEnumrable<T> Query<T>(string sqlQuery, object param);   T FirstOrDefault<T>(string sqlQuery, object param);   int Count(string sqlQuery, object param);   void Execute(string sqlCommand, object param);   void ExecuteScalar(string sqlCommand, object param);
}

这个接口中我们看到有数据库的连接、数据的查询 和 数据的处理 三个职责。

这三个职责我们需要分开吗?这依赖于应用程序的变化方式。若果说应用程序的变化会影响到连接函数的签名(可能是连接字符串,也可能是 config 中的连接字符串名称),那么这个设计可能存在不合理。也可能代码中某些地方只需要开放查询功能。

另一方面,若果应用程序的变化方式总是会导致这三个职责同时变化,那么就不需要分离他们。实际上,分离他们会导致不必要的复杂性。

分离耦合职责

如何分离耦合的职责呢?我们可以分离它们的接口来进行解耦。将多功能的大接口分解成多个单功能的小接口。

public interface IRdbmsStorageQuery
{
  IEnumrable<T> Query<T>(string sqlQuery, object param);   T FirstOrDefault<T>(string sqlQuery, object param);   int Count(string sqlQuery, object param);
} public interface IRdbmsStorageCommand
{
  void Execute(string sqlCommand, object param);   void ExecuteScalar(string sqlCommand, object param);
} public interface IRdbmsStorage : IRdbmsStorageQuery, IRdbmsStorageCommand
{
  IDbConnection Connection(string connectionString);
}

上述代码中我们换分成了 IRdbmsStorageQuery 查询接口 和 IRdbmsStorageCommand 命令 接口(有点 CQS 的味道),然后通过 IRdbmsStorage 接口组合起来。在有些地方我们可能只需要查询功能,有些地方可能用到执行功能,而有些地方可能两者都需要用到。

总结

SPR 原则可以说是面向对象原则中最简单的原则之一,但是也是最难把握的原则之一。软件设计真正要做的许多工作,就是要发现职责并把那些职责相互分离开来。这些职责什么时候该划分职责,划分的颗粒度又有多大,都需要我们去体会。

OOD/DDP 中的 SRP 原则的更多相关文章

  1. TypeScript 中的 SOLID 原则

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

  2. 连载:面向对象葵花宝典:思想、技巧与实践(30) - SRP原则

    前面具体阐述了"高内聚低耦合"的整体设计原则.但怎样让设计满足这个原则,并非一件简单的事情.幸好各位前辈和大牛已经帮我们归纳总结出来了,这就是"设计原则"和&q ...

  3. 设计原则:单一职责(SRP)原则

    1 什么是单一职责(SRP)原则 单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP.翻译过来就是:一个类或者模块只负责完成一个职责(或者功能). 所 ...

  4. ASP.NET 设计模式中依赖倒置原则

    依赖倒置原则 A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象. B.抽象不应该依赖于具体,具体应该依赖于抽象. 依赖倒置原则 A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于 ...

  5. PCB设计中的20H原则

    20H原则是指电源层相对地层内缩20H的距离,当然也是为抑制边缘辐射效应.在板的边缘会向外辐射电磁干扰.将电源层内缩,使得电场只在接地层的范围内传导.有效的提高了EMC.若内缩20H则可以将70%的电 ...

  6. python中的继承原则

     继承是面向对象的重要特征之一,继承是两个类或者多个类之间的父子关系,子进程继承了父进程的所有公有实例变量和方法.继承实现了代码的重用.重用已经存在的数据和行为,减少代码的重新编写,python在类名 ...

  7. Numpy中的广播原则(机制)

    为了了解这个原则,首先我们来看一组例子: # 数组直接对一个数进行加减乘除,产生的结果是数组中的每个元素都会加减乘除这个数. In [12]: import numpy as np In [13]: ...

  8. JMM中的Happens-Before原则

      在java内存模型中,happens-before应该理解为:前一个操作的结果,可以被后续的操作获取,即内存可见性.   为了解决多线程的内存可见性问题,就提出了happens-before原则, ...

  9. 微服务中的CAP原则

    CAP原则:指的是在一个分布式系统中,Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),三个要素最多同时实现两点不可能同时实 ...

随机推荐

  1. 配置toad进行导入导出数据库操作

    最近需要对oracle进行导入导出操作,于是研究使用toad进行导入导出oracle数据库操作,现稍作记录. oracle的导入导出不管是否使用toad还是pl/sql工具进行操作,实际上最终都是通过 ...

  2. select/**/*/**/from/**/RegSite

    select/**/*/**/from/**/RegSite  这样写sql也是可以的 替换空格

  3. 程序员带你十天快速入门Python,玩转电脑软件开发(三)

    声明:本次教程主要适用于已经习得一门编程语言的程序员.想要学习第二门语言.有梦想,立志做全栈攻城狮的你 . 如果是小白,也可以学习本教程.不过可能有些困难.如有问题在文章下方进行讨论.或者添加QQ群5 ...

  4. C#实现动态网站伪静态,使seo更友好

    本教程将使用Visual Studio 2013手把手教你实现webform动态页面的伪静态.本教程配套的C#源码工程可通过我的github下载.地址:https://github.com/shell ...

  5. Java-struts2 之中文乱码问题

    中文乱码问题,是个很麻烦的问题,有时候你发现,你表单页面的编码是UTF-8 Stutrst.xml也有这么一句话 <constant name="struts.i18n.encodin ...

  6. .NET多线程同步方法详解

    .NET多线程同步方法详解(一):自由锁(InterLocked) .NET多线程同步方法详解(二):互斥锁(lock) NET多线程同步方法详解(三):读写锁(ReadWriteLock) .NET ...

  7. orm fluentdata使用相关文章

    微型orm fluentdata使用:http://www.360doc.com/content/12/1228/23/9200790_256885743.shtml

  8. js中push()方法

    直接上代码: var roleIdsTemp = []; $("#addRole .modalcheckbox-all").each(function(key, value) {  ...

  9. Shell: extract more from listener.log(分析监听日志)

    最近遇到了两起数据库连接数不足的问题, 通常都会预留一些会话增加的情况, 但在一些特殊情况下如连接风暴(logon storm), 如果在监听中没有做rate限流,对数据库来说巨大的冲击可能会导致数据 ...

  10. 使用Reveal.app调试整个项目UI时间,增加LD指令 -Objc引起项目中多个静态库冲突问题

    今天接触到一个新的UI调试工具教程如下: iOS真机UI调试利器——Reveal 引入增加-ObjC -framework Reveal指令后,发现项目出现多重静态库冲突问题, 首先介绍一个指令: - ...