彻底弄懂类设计原则之 - 单一职责原则

待兔
• 阅读 1217

类设计原则之 - 单一职责

类的设计原则之单一职责原则,是最常用的类的设计的原则之一

英文: SRP , Simple Responsibility Principle

中文:单一职责原则

这是面向对象类设计中的第一个原则 ,也是看起来最简单的一个原则,但是实际上远远没有这么简单,很多人不一定真正理解了!

类设计,通俗的讲就是怎么去写一个类更好,应该遵循什么样的原则设计类更好。

我们随便找几个网上的解释:看看各位大师或者经典网站是怎么解释的。

百度百科:就一个类而言,应该仅有一个引起它变化的原因。应该只有一个职责。

说句实在话,我最开始也是对这句话似懂非懂,看的不是太明白,因为,引起一个类变化 的原因太多了,比如

  • 给类增加一个方法是变化吧?
  • 给类增加一个属性是变化吧?
  • 给类的方法增加一个函数是变化吧?
  • ......

引起这些变化的原因太多了,如果每个原因都是一个职责,那么SRP简直就无法判断了!

维基百科:(内容基本上和百度百科一致),通俗的讲就是:一个类只做一件事

这个解释更通俗易懂,也更符合中国人的理解。但是仔细想想,还是有几个地方比较难理解:

什么叫做 “一件事” ?

举个例子:

比如有一个学生管理类,这个类有 添加学生信息 , 修改学生信息查询学生信息删除学生信息

问题来了, 这是 4 件事 ? 还是 1 件事 ?

看起来好像是 4 件事, 但是稍有经验的人都知道,这 4 件事都是由一个类来实现的,而不是设计 4 个类!

所以问题的关键在于:什么是 “一件事” ? 是每个功能一件事吗?

其实答案就在我们自己身上, 因为只要我们工作,就无时无刻的在承担着一定的职责

现在抛开面向对象,抛开软件,抛开计算机,来看看我们自己的职责

  1. 比如我是一个程序员,我的职责是写程序 , 但 写程序 有很多事情,例如 编码单元测试系统测试bug修复开会写文档
  2. 比如我的老板是一个管理者,他的职责是 管理程序员 ,他也有很多工作,例如 制订计划 , 团队建设开会 ,协调 绩效考评
  3. 比如我是一个快递员,我的职责是送快递,但是我也有很多事要做,例如 分包 , 快递 ,收款 , 开会

这些职责都不是我们自己定义的,而是公司或者部门或者组织,给我们安排工作的时候定义的。

也就是说,职责 是站在他人的角度上定义的,而不是我们自己定义的。

经过我们对职责 定义的分析,我们可以得出 2 个关于职责的重要结论

  • 职责是站在他人的角度上定义的
  • 职责不是一件事,而是很多事,但这些事都是和职责紧密结合的。

对应到面向对象设计领域,我们可以说一个类的职责应该如下定义:

  • 类的职责是站在其它类的角度来定义的
  • 类的职责包含多个相关功能

因此,SRP 可以翻译为 一个类只负责一组相关的事 , 对应到代码中就是:一个类有多个方法,这些方法是相关的

有了这个定义,我们再来看看学生信息管理类, 很明显,它具有的 4 个功能都是和 管理 相关的,按照 SRP 应该只设计一个学生信息管理类就可以了。

欢迎关注我们的 HelloWorld开发者社区, www.helloworld.net ,很好记的域名哦

SRP 的应用范围

但是现实世界往往比理想更复杂,一个最典型的例子就是 办公一体化

根据 SRP , 打印机可以设计成一个类,复印机可以设计成一个类,扫描仪可以设计成一个类,传真机也可以设计成一个类

但偏偏就出了一个 办公一体化 , 这个机器集成了 打印复印扫描 , 传真 4 个职责 !

如果我们设计一个 办公一体化 的类,怎么也不可能设计出一个符合 SRP 的 办公一体化的类

怎么办? 是 SRP 不正确 ? 还是我们永远都不要设计一个 办公一体化 的类 ?

其实 SRP 没有错, 办公一体化 也应该设计, 但是不要用 SRP 原则来约束 办公一体化 这样的类!

也就是说, SRP 其实是有适用范围的, SRP 只适合那些基础类,而不适合基于基础类构建复杂类的聚合类

办公一体化 的样例中, 打印机 ,复印机 ,扫描仪传真机 都是基础类,每个类都承担一个职责

办公一体化 是一个聚合类, 同时集成了4种功能!

细心的你可能发现了:SRP不能应用于聚合类, 那么如何保证聚合类的设计质量呢?

换句话说,遇到这样的情况,如何设计这样的聚合类呢?

这个问题在 GoF 的 《设计模式》 一书中有详细的答案,即优先使用对象组合 ,而不是类继承。

类的单一原则就到这里了,现小结一下:

  • 类的单一原则(SRP):一个类只负责一组相关的事, 对应到代码中就是:一个类有多个方法,这些方法是相关的
  • 职责是站在他人的角度上定义的
  • 类的职责包含多个相关功能
  • SRP 只适合那些基础类,而不适合基于基础类构建复杂类的聚合类
  • 对于复杂的聚合类,优先使用组合 ,而不是继承
  • 最后一条,欢迎关注我们的HelloWorld开发者社区 , 网址:www.helloworld.net ,域名很好记哦

欢迎关注我们的下一篇文章,出讲解更多的类设计的原则。

点赞
收藏
评论区
推荐文章
xiguaapp xiguaapp
2年前
一句话总结java七大设计原则
开闭原则:对扩展开放,对修改关闭。依赖倒置原则:高层应该不依赖地层。单一职责原则:一个类只干一件事儿。接口隔离原则:一个接口只干一件事儿迪米特法则:不该知道的就不要知道。里氏替换原则:子类重写方法功能发生改变,但是不影响父类方法的语义。合成复用原则:尽量使用组合实现代码复用,不要用继承,要解耦。
Wesley13 Wesley13
2年前
java之设计模式
看了设计模式,感觉自己很多不理解什么意思,通过看博客别人写的理解,总结了一下,方便查阅。一、设计模式六大原则1、单一职责原则:定义:应该有且只有一个原因引起类的变化。注意:这里的类不光指类,也适用于方法和接口,比如我们常说的一个方法实现一个功能。2、开放封闭原则:定义:类、模块、函数等
亚瑟 亚瑟
2年前
面向对象设计原则
面向对象设计原则对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一。7种常用的面向对象设计原则|设计原则名称|定义|使用频率||
待兔 待兔
3年前
聊聊软件设计原则
软件设计知识是一名软件开发人员必须要懂的知识,最近几天今天看了bob大叔的《敏捷软件开发》一书和软件设计相关的一些blog和资料,自己做了一个学习笔记设计目标正确性、健壮性、灵活性、可重用性、高效性降低复杂性所谓复杂性,就是任何使得软件难于理解和修改的因素。复杂性的来源主要有两个:代码的含义模糊和互相依赖
zdd小小菜鸟 zdd小小菜鸟
1年前
设计模式–六大原则
设计模式–六大原则tex在238中设计模式中,我们提炼出了六大面向对象设计原则我们可以不知道那数量繁多的设计模式,但一定要记住这六大设计原则1.开闭原则(OpenClosePrinciple
待兔 待兔
2年前
彻底弄懂类设计原则之 - 开闭原则
类设计原则之开闭原则OCP,OpenClosedPrinciple,中文翻译为开闭原则当第一次看到OCP时,我就蒙了,什么开,什么闭啊,完全摸不到头脑然后就去网上找各种博客,各种解释,最多的一种就是:对扩展开放,对修改关闭当时我就更蒙了,去问了很多“高手”,他的回答让我更加迷茫:不修改代码就可以增加新功能这是多么神奇的事啊,不修改代码
zdd小小菜鸟 zdd小小菜鸟
1年前
设计模式面试
设计模式面试1.单例设计模式使用设计模式为了代码复用,增加可维护性。设计模式的六大原则:开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、迪米特法则(最少知道原则)、合成/聚合复用原则Singleton(创建):保证一个类仅
Wesley13 Wesley13
2年前
C#简单工厂模式
C简单工厂模式模型,建立一个模型,构建我们的实际工程,项目。​所有面向对象的编程都是在我们生活中存在的,从词义的解释就是我们生活中的工厂就是负责生产产品的,而到开发中对应的就是NEW不同的对象,该模式主要解决的问题就是解决创建对象与该类的解耦。设计原则中经常说的类单一职责、封装性都有体现。编程中的简单工厂就是一个生产
Stella981 Stella981
2年前
From Apprentice To Artisan 翻译 16
上一篇(https://my.oschina.net/zgldh/blog/379461)SingleResponsibilityPrinciple单一职责原则Introduction介绍The"SOLID"design
Wesley13 Wesley13
2年前
6 个重构方法可帮你提升 80% 的代码质量
在过去做了不少代码走读,发现了一些代码质量上比较普遍的问题,以下是其中的前五名:1.臃肿的类: 类之所以会臃肿,是因为开发者缺乏对最基本的编码原则,即“单一职责原则”(SRP)的理解。这些类往往会变得很臃肿,是由于不同的且在功能上缺少关联的方法都放在了相同的类里面。2.长方法: 方
待兔
待兔
Lv1
男 · helloworld公司 · CTO - helloworld开发者社区站长
helloworld开发者社区网站站长
文章
89
粉丝
43
获赞
75