单一职责原则(Single Responsibility Principle),缩写为SRP。

SRP的定义是:There should never be more than one reason for a class to change

一个类应该只有一个引起它变化的原因。

也就是:一个类或模块应该只有一个职责。

就是说,不要大而全的类,要粒度小、功能单一的类。一个类不应该包括了两个或者两个以上的不同业务功能,应该将不同的业务功能拆分成多个功能单一,粒度更细的类中。

如何判断类的职责是否单一?

王者荣耀大家应该看过吧,在登录王者荣耀成功的时候,会显示用户的相关信息,包括:头像、昵称以及现有的金币、钻石、点券等信息。

根据这个用户信息,我们可以定义这样的一个用户信息类:

public class UserInfo {private String portrait;//头像private String nickname;//昵称private int glod;//金币private int diamond;//钻石private int point;//点券//setter & getter ...
}

你觉得,这个UserInfo类的设计上是否满足单一职责原则呢?实际上,如果UserInfo中定义的信息如果只是在这个界面中使用,只是单纯的用来展示,虽然这个类中包括了不仅仅是用户的基本信息,还包括了资金的相关信息,两者好像本身就不符合单一职责原则,但是对于仅展示信息来说,这个类的设计还是合理的。

那么,在什么情况下这个类的设计会变得不满足单一职责原则呢?在王者荣耀中,用户的资金信息在不同的界面中有不同的显示需求,比如在抽奖界面中,显示钻石与点券,此时并不需要用户的头像、昵称等信息。

此时,如果要满足单一职责原则,则需要将用户的基础信息与资金相关信息相分离,抽取成独立的类。

在这里的单一职责原则的改变有以下几个原因:

  • 避免网络开销。网络带宽是一个非常珍贵的资源,特别是在高并发的场景下,每次交互能节省一点数据量,在高并发场景下是非常可观的节省。

  • 避免多个的变更点,也就是要符合只有一个原因引起类的变化。在上面的代码中,头像需要添加对应的边框,则需要修改UserInfo类,而如果资金要变更,也同时需要变更UserInfo类,存在多个维度的原因引起UserInfo类的变化。

从这个示例中,我们可以看到,其实单一职责原则并不能一概而论的,需要根据不同的场景,不同的阶段需求来进行判定。在一些场景中或者在当前的需求中,设计上满足单一职责原则,但是如果更换了场景或者需求,则可能设计上就不满足单一职责原则了。

所以,如何评价一个类是否满足单一职责原则,并没有一个明确的,可以量化的标准,需要根据实际情况而定。

有了以上的概念,我们再来看一个实际应用例子。还是以王者荣耀为例,王者荣耀的抽奖中,用户抽奖,然后将奖品放到用户的背包中。我们先来看一下这个实现的类图:

这样的设计满足了初期的抽奖需求,但是后面,王者荣耀的抽奖要支持:钻石以及点券二种抽奖方式,修改后类图如下:

将抽奖分为:钻石抽奖以及点券抽奖二个方法,然后根据奖品再将奖品发送给用户。而随着游戏的进行,背包的数据太大,需要限制背包的大小,所以,当背包容量不足,奖品无法放入背包时,需要将奖品以邮件的方式发送。我们需要修改类支持二种奖品的发送模式。

所以,我们可以看到,Lucky接口的定义是不稳定的,它有二个职责:1. 抽奖 2. 发送奖品。其中任意一个业务发生变化的时候,都需要修改Lucky接口,Lucky接口的变化不仅仅只有一个原因,而是有多个原因。这就不符合:单一职责原则。所以,需要将二个职责分离,抽象出二个接口:

这样在当前的时刻就满足单一职责原则了,每个接口职责明确,结构清晰,同时如果需要修改,则只需要变更较细粒度的接口,影响面较小。

单一职责带来的好处

软件需求,唯一不变的就是变化。如果一个类的职责过多,就等于把这些不同的责任耦合在一起,一个职责的变化可能会影响其他的职责,导致设计脆弱,当变化发生时,可能会有意想不到的破坏。

所以单一职责可以带来以下好处:

  • 降低了类的复杂度,单个类的职责清晰,这个类就不会那么复杂

  • 提高可读性:类的复杂度降低了,类职责清晰明确,容易看懂

  • 提高可维护性:容易看懂,就比较容易修改维护

  • 降低风险性:修改只影响该类的相应依赖类,不影响其他的职责类,影响面小

小结

单一职责是最容易理解的原则,但是却是最难应用的原则。

如何划分职责,是一个比较大的挑战。

单一职责的职责如何定量并没有标准,需要结合项目实际考虑。

从功能上来说,定义一个大而全的类并没有错,因为实现简单,设计简单,这也是在项目中常见的设计。但是项目实施需要考虑变化因素和不变化的因素,及其带来的收益。但是,如果从扩展的角度来思考的话,有多个变化的原因设计在一个接口内,意味着如果以后有变化,则会带来更大的风险(改动大,风险也大)。

那么,到底需不需要严格遵守单一职责原则?单一职责原则通过避免设计大而全的类,避免不相关的功能耦合在一起,类与类之间依赖减少,降低了代码的耦合性。但是如果拆分过细,又会适得其反,降低代码的内聚性,接口过多,影响代码的可维护性。

最后建议:单一职责原则根据需求、场景来决定是否遵守,接口设计尽最大可能做到单一职责,类尽量做到只有一个原因引起变化。

设计原则SOLD之 —— 单一职责原则SRP相关推荐

  1. 面象对象设计6大原则之一:单一职责原则

    转载自 面象对象设计6大原则之一:单一职责原则 单一职责原则(SRP),The Single Responsibility Principle 定义 一个类的修改只能有一个被修改的原因. 通俗地讲,就 ...

  2. 设计模式-02.经典设计原则-第一节-单一职责原则,开闭原则,里式替换,接口隔离【万字长文系列】

    文章目录 设计模式经典设计原则-第一节 单一职责原则(SRP) 如何理解单一职责原则? 如何判断类的职责是否足够单一? 类的职责是否设计得越单一越好? 开闭原则(OCP) 如何理解"对扩展开 ...

  3. 设计原则之【单一职责原则】

    文章目录 什么是单一职责原则 案例 如何判断一个类的职责是否单一? 类的职责是否越单一越好? 总结 参考资料 什么是单一职责原则 单一职责原则的英文是 Single Responsibility Pr ...

  4. 设计模式原则篇:(1)单一职责原则--Single Responsibility Principle

    上篇文章提及到设计模式中应遵循的设计原则,并且列出了设计模式中应当遵循的六大原则. 次篇文章主要讨论单一职责原则. 单一职责原则(SRP): 不要存在多于一个导致类变更的原因.简单的讲,就是一个类或接 ...

  5. [转]设计模式六大原则[1]:单一职责原则

    定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责. 问题由来:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的 ...

  6. 面向对象设计原则之一:单一职责原则

    单一职责原则(Single Responsibility Principle SRP) There should never be more than one reason for a class t ...

  7. 【编码魔法师系列_六大原则1】单一职责原则(Single Responsibility Principle)

    学会设计模式,你就可以像拥有魔法一样,在开发过程中解决一些复杂的问题.设计模式是由经验丰富的开发者们(GoF)凝聚出来的最佳实践,可以提高代码的可读性.可维护性和可重用性,从而让我们的开发效率更高.通 ...

  8. 经典设计原则:单一职责原则(SRP)

    本文详解设计原则中的单一职责原则,目的还是提高代码的可读性.可扩展性.复用性.可维护性等. 目录 1. 单一职责原则(SRP) 2. 如何理解单一职责原则? 3. 如何判断类的职责是否足够单一? 4. ...

  9. 软件设计原则(二)单一职责原则 -Single Responsibility Principle

    SRP,Single Responsibility Principle: There should never be more than one reason for a class to chang ...

  10. 五大软件设计原则学习笔记1——单一职责原则

    五大软件设计原则SOLID: 单一职责原则(Single responsibility principle,SRP) 开放封闭原则(Open–closed principle,OCP) Liskov ...

最新文章

  1. 用 async/await 来处理异步
  2. 树莓派(Raspberry Pi)修改时区
  3. python 安装serial模块
  4. 盒马鲜生颠覆传统生鲜市场的胜算几何?
  5. slf4j介绍及配置详解
  6. pip安装lxml报错
  7. css3 多列布局使用
  8. 权限管理快速入门_01
  9. SQLLDR载数加速,优化参数
  10. Android boot.img system.img ramdisk.img的解释
  11. echarts全解析及其用法详解
  12. 早上如何泡上一杯质量上佳的柠檬水
  13. 大数据-Redis基础
  14. 2008服务器系统初始密码,2008服务器地址和密码
  15. Vue函数传参之event触发
  16. 全自动软化水设备:全自动软化水设备选型指南
  17. 新品发布会直播推广的优势
  18. 职务犯罪嫌疑人的第十八天科达打造“镇江模式”
  19. 华为机试:计算最大乘积
  20. HTML+CSS系列学习 第五篇

热门文章

  1. 微信小程序前期申请企业认证、后期提审发布流程
  2. 如何快速比对表格数据
  3. 服务器修改传奇道士神兽升级,传奇游戏小道士关于神兽升级的研究——骨灰级传奇玩家分享...
  4. PMI与股市同期走势图
  5. Word删除连续分节符
  6. 计算机专业可以从事什么工作?
  7. 电脑图片格式怎么批量转换jpg?几个小妙招轻松转换
  8. 如果宇宙是答案,那么问题是什么?
  9. Python3,1行代码,去除图片的背景图,确实香。
  10. P1957 口算练习题[c++版]