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

简介:

前面详细阐述了“高内聚低耦合”的总体设计原则,但如何让设计满足这个原则,并不是一件简单的事情,幸好各位前辈和大牛已经帮我们归纳总结出来了,这就是“设计原则”和“设计模式”。毫不夸张的说,只要你吃透这些原则和模式并熟练应用,就能够做出很好的设计


==================================================================


【SRP原则详解】

SRP,single responsibility principle,中文翻译为“单一职责原则”!

 

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

 

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

百度百科(http://baike.baidu.com/view/1545205.htm):

一个类应该有且仅有一个职责。关于职责的含意,面向对象大师Robert.C.Martin有一个著名的定义:所谓一个类的职责是指引起该类变化的原因,如果一个类具有一个以上的职责,那么就会有多个不同的原因引起该类变化,其实就是耦合了多个互不相关的职责,就会降低这个类的内聚性。

说句实话,虽然是面向对象大师Martin的解释,我还是看得不甚明白:引起类变化的原因太多了,例如:

给类加一个方法是变化吧?

给类加一个属性是变化吧?

类的函数增加一个参数是变化吧?

。。。。。。

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

 

Wiki百科(http://en.wikipedia.org/wiki/Single_responsibility_principle )内容和百度百科基本一致,看起来百度百科像wiki百科的翻译:)

Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to change.

 

除了这些标准的解释外,还有一种说法:SRP就是指每个类只做一件事

这个解释更通俗易懂,也更加适合中国人理解。虽然比Martin大师的解释更清楚一些,但仔细想想,还是有个地方比较难以理解:什么叫做“一件事”

 

比如说一个学生信息管理类,这个类有“添加学生信息”、“查询学生信息”、“修改学生信息”、“删除学生信息”,那么这是4件事情,还是一件事情呢?

 

看起来好像是4个事情,但稍有经验的朋友应该都知道,这4个事情绝大部分情况下都是一个类来实现的,而不是分成4个类!

 

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

 

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

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

 

比如说,我是一个程序猿,我的职责应该是“写程序”,但写程序有很多事情,例如:编码,单元测试、系统测试,bug修复,开会,写文档。。。。。。

再比如说,我的BOSS是一个管理者,他的职责是“管理程序猿”,他也有很多工作,例如:制定计划,团队建设、开会、协调资源、写文档。。。。。。

又比如说,我是一个快递员,也有很多工作:分包、快递、收款、开会。。。。。。

 

这些职责其实都不是我们自己定义的,而是公司或者部门或者组织给我们安排工作的时候定义的,也就是说:“职责”是站在他人的角度来定义的,而不是自己定义的,也许你想把自己定义成CEO,但你的老板会真的让你当CEO么?

 

经过对我们自己的职责的分析,我们可以得出两个关于职责的重要结论:

1) 职责是站在他人的角度来定义的

2) 职责不是一件事,而是很多事情,但这些事情都是和职责紧密相关的

 

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

1) 类的职责是站在其它类的角度来定义的;

2) 类的职责包含多个相关功能;

 

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

 

当然,如果你再让我解释什么是“相关”,那我只能吐血了:)

 

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

 

【SRP原则范围】

但现实世界往往比理想要复杂,一个最典型的例子就是“办公一体机”。

根据SRP原则,打印机可以设计成一个类,复印机也可以设计成一个类,扫描仪也可以设计成一个类,传真机还是可以设计成一个类,但偏偏就是出了个“办公一体机”,这个机器集成了“打印、复印、扫描、传真”4个职责!

如果我们要设计一个“办公一体机”的类,怎么也不可能设计出一个符合SRP原则的“办公一体机”的类来!

 

怎么办?是SRP不正确么,还是我们永远都不要设计“办公一体机”这样的类?

 

其实SRP也没有错,“办公一体机”也应该设计,但:不要用SRP来约束“办公一体机”这样的类!

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

 

在“办公一体机“的样例中,“打印机”、“复印机”、“扫描仪”、“传真机”都是基础类,每个类都承担一个职责,而办公一体机是“聚合类”,同时集成了4种功能!

 

细心的朋友可能会继续问道:SRP不能应用于聚合类,那么如何保证聚合类的设计质量呢

这个问题的答案在GoF的《设计模式》一书中有详细的答案,即:优先使用对象组合,而不是类继承。详细内容请参考后续“设计模式”部分的内容


================================================ 
转载请注明出处:http://blog.csdn.net/yunhua_lee/article/details/25279539
================================================ 

相关文章
|
3月前
|
人工智能 并行计算 API
全网最全的GPT-5测评文章!1.8万字详细实战测评!国内直接使用!
OpenAI 发布了期待已久的 GPT-5,其在数学、编程、视觉理解和健康等领域表现卓越,推理能力媲美 Gemini 2.5 Pro,代码能力媲美 Claude 4。GPT-5 与 GPT-5-thinking 双模型协同工作,带来更高效体验。国内用户可通过指定平台直接访问,提供免费授权码体验。
685 0
|
10月前
|
机器学习/深度学习 数据采集
《机器学习模型快速收敛的秘籍大揭秘》
在机器学习中,快速收敛是提高效率和节省资源的关键。常用方法包括:选择合适的优化器(如Adam、RMSProp等),动态调整学习率,使用预训练模型,进行数据预处理,合理选择模型结构,应用批量归一化,以及增加训练数据。这些策略能有效加速模型收敛,提升性能并减少训练时间。
391 7
|
8月前
|
人工智能 Linux iOS开发
Linux下搭建本地deepseek(附文档下载)
本文介绍了在Linux上搭建本地DeepSeek的步骤。主要涉及安装ollama、下载deepseek模型(1.5b参数版本)和配置ChatboxAI客户端。通过命令行安装ollama后,使用`ollama run deepseek-r1:1.5b`下载模型,并配置环境变量以确保服务正常运行。最后,通过ChatboxAI与模型进行交互。整个过程适合初学者,服务器配置为4核CPU和8GB内存,无GPU,响应速度稍有延迟但可接受。相关资源链接已提供。
1135 2
|
人工智能 自然语言处理 安全
创新场景丨后土“量地”,跨模态大模型让自然资源管理有“速度”更有“温度”
“通过需求引领、底座支撑、数字转型、场景驱动、智慧赋能,全面支撑自然资源数字化治理能力提升,最终答好自然资源数字化治理过程中的必答题。
|
缓存 应用服务中间件 Apache
缓存代理服务器的实现机制和技术选型
缓存代理服务器是一种特殊的代理服务器,其主要功能是缓存从目标服务器(通常是Web服务器)获取的数据,并在客户端再次请求相同数据时直接提供缓存的数据。通过缓存代理服务器可以加快访问速度并减轻目标服务器的负载。
589 100
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
随着移动应用市场的蓬勃发展,用户对界面设计的要求日益提高。为此,掌握由Google推出的Material Design设计语言成为提升应用颜值和用户体验的关键。本文将带你深入了解Material Design的核心原则,如真实感、统一性和创新性,并通过丰富的组件库及示例代码,助你轻松打造美观且一致的应用界面。无论是色彩搭配还是动画效果,Material Design都能为你的Android应用增添无限魅力。
349 1
|
JavaScript
vue + element-ui + qrcodejs2 实现二维码生成
1、在所在项目下安装插件 ```js npm i qrcodejs2 ``` 2、在需要生成二维码的页面引入qrcodejs ```js import QRCode from 'qrcodejs2' ``` 3、使用 ```html <el-button size="mini" type="primary" icon="el-icon-picture-outline" round @click="GenerateQRCode()">生成二维码</el-button></div> <div id="qrcode" ref="qrcode"></div> ``` 回调函数 ```js //
316 0
|
机器学习/深度学习 人工智能 自然语言处理
大厂技术实现 | 多目标优化及应用(含代码实现)@推荐与计算广告系列
推荐,搜索,计算广告是互联网公司最普及最容易商业变现的方向,也是算法发挥作用最大的一些方向,前沿算法的突破和应用可以极大程度驱动业务增长,这个系列咱们就聊聊这些业务方向的技术和企业实践。本期主题为多目标学习优化落地(附『实现代码』和『微信数据集』)
7892 6
大厂技术实现 | 多目标优化及应用(含代码实现)@推荐与计算广告系列
|
网络协议 调度
电脑为什么需要操作系统?底层原理是什么?
电脑为什么需要操作系统?底层原理是什么?
567 0
|
消息中间件 JavaScript Java
比 Nginx 性能更强的下一代 Web 服务器
比 Nginx 性能更强的下一代 Web 服务器