单一职责原则

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. HTML5 新功能

    HTML5 中的一些有趣的新特性: 用于绘画的 canvas 元素 用于媒介回放的 video 和 audio 元素 对本地离线存储的更好的支持 新的特殊内容元素,比如 article.footer. ...

  2. [转]eclipse github 提交代码

    1 git add2 git commit3 git pull  (会产生冲突) 分成自动合并和手动合并4 处理冲突的文件 5 git push 本次commit 我用的是Eclipse的插件EGit ...

  3. C#中Hashtable、Dictionary详解以及写入和读取对比

    转载:http://www.cnblogs.com/chengxingliang/archive/2013/04/15/3020428.html 在本文中将从基础角度讲解HashTable.Dicti ...

  4. SqlServer中的merge操作,相当地风骚

    今天在一个存储过程中看见了merge这个关键字,第一个想法是,这个是配置管理中的概念吗,把相邻两次的更改合并到一起.后来在technet上搜索发现别有洞天,原来是另外一个sql关键字,t-sql的语法 ...

  5. MySQL Workbench 6.3 CE 不显示MySql、infomation_schema等数据库

    MySQL Workbench 6.3 CE 不显示MySql.infomation_schema等数据库 通过修改偏好设置可显示: 1.Edit-->Preferences....-----& ...

  6. UIAlertController使用的一个坑

    / // 创建一个确定按钮”一定要注意不能在提醒控制器的按钮的点击方法内部用到提醒控制器自己”,不能把下面这句话放在block内部”不然会死循环,导致警告控制器不能销毁" UITextFie ...

  7. 1 Winform 异步更新控件

    刚才看到有人问为了winfrom中,在大数据绑定的时候出现画面假死的状态,为了解决这个问题希望通过再开一个线程来给控件绑定数据,可是画面还是会假死.现在看到的方法有1.掩耳盗铃法(Control.Ch ...

  8. ZOJ 3725 Painting Storages(DP+排列组合)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5048 Sample Input 4 3 Sample Output ...

  9. easyui-combobox小Demo

    <script type="text/javascript"> $("#Function_TypeSelect").combobox({ onSel ...

  10. node初步二 小爬虫

    小爬拉勾网 获取想要的信息: 一.分三步 1 获得数据 2 处理数据 3展示数据 二 .代码 :创建文件reptile.js;写入 var http=require('http'); var chee ...