[面向对象]The Single Responsibility Principle

SRP:TheSingle Responsibility Principle

单职原则

None but Buddha himself must take theresponsibility of giving out occult secrets...

E. Cobham Brewer1810–1897.

Dictionaryof Phrase and Fable. 1898.

(译者注:一开始翻译就遇到这句很难翻译的了,本人的理解为“就连佛祖都有他的职责”)

 

        SRP原则是TomDeMarco Meilir Page-Jones在工作的时候提出的。他们称这个原则为“内聚”。在21章,我们说给出更多在的Package层次的定义说明。这个SRP原则是针对Class层次的。

 

SRP:单职原则

        修改一个类的理由不应该超过一个。

        

以第六章的保龄球游戏为例子。Game这个类拥有2个完全独立的职责。它不停地追踪每一帧,并进行分数计算。最后它被分割为RCMRSK类。Game类保持其原有追踪帧与计算得分的职责。

        为什么将这2个职能分割到2个类中呢?这是因为这2个职能都是以其自身为修改点的。我们只需要修改对应类就可以修改对应的职能。一个类超过一个职能,那么我们将会有多个原因去修改它(译者注:一个职能的修改归结为一个原因)。

        

        例如图9-1的设计。Rectangle类有2个方法。一个是渲染矩形到屏幕,另一个是计算矩形的面积。

 

超过一个职能

        2个不同的程序去使用Rectangle类。一个程序是几何运算程序,需要使用Rectangle类来进行对几何图形进行数学运算,它并不需要将矩形输出到屏幕。另一个程序是图像显示程序,它在需要几何运算的同时也需要将矩形输出到屏幕上。

        这个设计违背了SRP。矩形有2个职责,一是计算面积,二是GUI相关的渲染。

        违背SRP会导致一些问题。

首先,这样的Rectangle类,需要包含GUI相关代码到几何运算程序中。如果它是一个C++程序,那么就需要link相关的GUI库了,增加了complielink内存的开销。如果是一个JAVA程序,那么它也需要依赖相关平台的GUI库。

        其次,如果图像显示程序,需要修改Rectangle类,那么几何运算程序,如果你忘记了做这一步,那么几何运算程序将会因为函数指针的偏移而导致程序随时崩溃。

        

        一个比较好的设计就是将职能划分,如图9-2。将渲染和面积计算划分到不同的类,这样2个程序就独立开来了。

        

 

什么是职能?

 

上文我们将SRP定义为一个职能职能因为“一个理由而去改变”。如果你有多于一个动机去改变一个类,那么这个类其实就是有多个职能了。很多时候,这个情况是很困难发现的。我们习惯将一个逻辑归到一个职能中。例如下面表格9-1Modem这个interface。大多数人都认为它是比较合理的。Modem4个功能分别由4个函数去声明。

 

        然而,其实它隐含了2个职能。dialhangup函数属于通信管理,sendrecv属于数据传输。

        2个职能是否应该分隔呢?在大多数的情况下,他们都应该被分隔。这2组函数几乎没有共同之处。修改他们肯定是出于不同的理由。此外,这2组函数也会被不同的程序模块去调用。这些差异也导致了修改原因的差异。

        因此图9-3的设计就比较合理。将其只能分隔到2interface中。最后客户端程序将2个接口进行连接。

        然而,你会发现我又将2个职能归结到ModemImplementation类中了。虽然让人不爽,但这是必须的。我们经常会因为一些原因,如硬件或者操作系统,导致我们将一些东西耦合起来。但是,将他们分隔到不同的interface的话,我们又需要将剩余的部分进行解耦。

        我们可以将ModemImplementation类看作是一个组装机。需要注意的是所有的依赖都会从它消失。因为其他所有类都不依赖与它。除了main函数,其他类都没不需要知道它的存在。因此,我们将这些丑陋的实现都放到ModemImplementation里面,而且丑陋的实现又不会污染程序的其他部分。

 

结论

SRP是一个最简单的原则,但也是最难做得好的。我们很自然地将职责连接起来。所谓软件设计,其实就是寻找职责并将其分隔。剩下我们将要讨论的原则都用这样或那样的方式回到SRP这个点上。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值