面向对象的原则之单一职责原则

单一职责原则(Single Responsibility Principle, SRP):

一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。


  亚当·斯密曾就制针业做过一个分工产生效率的例子。对于一个没有受过相应训练,又不知道怎样使用这种职业机械的工人来讲,即使他竭尽全力地工作,也许一天连一根针也生产不出来,当然更生产不出20根针了。但是,如果把这个行业分成各种专门的组织,再把这种组织分成许多个部门,其中大部分部门也同样分为专门的组织。把制针分为18种不同工序,这18种不同操作由18个不同工人来担任。那么,尽管他们的机器设备都很差,但他们尽力工作,一天也能生产12磅针。每磅中等型号针有4000根,按这个数字计算,十多个人每天就可以制造48000根针,而每个人每天能制造4800根针。如果他们各自独立地工作,谁也不专学做一种专门的业务,那么他们之中无论是谁都绝不可能一天制造20根针,也许连1根针也制造不出来。这就是企业管理中的分工,在面向对象的设计里,叫做单一职责原则(Single Pesponsibility Principle,SRP)。

  在《敏捷软件开发》中,把“职责”定义为“变化的原因”,也就是说,就一个类而言,应该只有一个引起它变化的原因。说的简单点就是怎样设计一个类以及类的方法界定问题。这种问题很普遍,比如在MVC框架中,很多人会有这样的疑惑,对于表单插入数据库字段过滤与安全检查应该是放在control层处理还是model层处理,这类问题可以归到单一职责的范围。

  单一职责有两个含义:一个是避免相同的职责分散到不同的类中,另一个是避免一个类承担太多职责


那为什么要遵守SRP呢?

  1. 可以减少类之间的耦合。

      如果减少类之间的耦合,当需求变化时,只修改一个类,从而也就隔离了变化;如果一个类有多个不同职责,它们耦合在一起,当一个职责发生变化时,可能会影响其他职责。

  2. 提高类的复用性

      修理电脑比修理电视机简单多了。主要原因就在于电视机各个部件之间的耦合性太高,而电脑则不同,电脑的内存、硬盘、声卡、网卡、键盘灯部件都可以很容易地单独拆卸和组装。某个部件坏了,换上新的即可。

      上面的例子就体现了单一职责的优势。由于使用了单一职责,使得“组件”可以方便地“拆卸”和“组装”。

      不遵守SRP会影响对该类的复用性。当只需要复用该类的某一个职责时,由于它和其他的职责耦合在一起,也就很难分离出。


遵守SRP在实际代码开发中有没有什么应用?

  有的。以数据持久层为例,所谓的数据持久层主要指的是数据库操作,当然,还包括缓存管理等。以数据库操作为例,如果是一个复杂的系统,那么就可能涉及多种数据库的相互读写等,这时就需要数据持久层支持多种数据库。应该怎么做?定义多个数据库操作类?你的想法已经很接近了,再进一步,就是使用工厂模式。

  工厂模式(Factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。以数据库为例,工厂需要的就是根据不同的参数,生成不同的实例化对象。最简单的工厂就是根据传入的类型名实例化对象,如传入MySQL,就调用MySQL的类并实例化,如果是SQLite,则调用SQLite的类并实例化,甚至可以处理TXT、Excel等“类数据库”。工厂类也就是这样的一个类,它只负责生产对象,而不负责对象的具体内容。

  设计模式里面的命令模式也是SRP的体现,命令模式分离“命令的请求者”和“命令的实现者”方面的职责。举一个很好理解的例子,就是你去餐馆吃饭,餐馆存在顾客、服务员、厨师三个角色。作为顾客,你只要列出菜单,传给服务员,由服务员通知厨师去实现。作为服务员,只需要调用准备饭菜这个方法(对厨师大喊“该炒菜了”),厨师听到要炒菜的请求,就立即去做饭。在这里,命令的请求和实现就完成了解耦。

  在设计模式方面,不仅以上这两种体现了SRP,还有别的(比如代理模式)也体现了SRP。SRP不只是对类设计有意义,对以模块、子系统为单位的系统架构设计同样有意义。

  模块、子系统也应该仅有一个引起它变化的原因,如MVC所倡导的各个层之间的相互分离其实就是SRP在系统总体设计中的应用。


一些简单的应该遵循的做法如下:

  根据业务流程,把业务对象提炼出来。如果业务流层的链路太复杂,就把这个业务对象分离为多个单一业务对象。当业务链标准化后,对业务对象的内部情况做进一步处理。把第一次标准化视为最高层抽象,第二次视为次高层抽象,以此类推,直到“恰如其分”的设计层次。

  职责的分类需要注意。有业务职责,还要有脱离业务的抽象职责,从认识业务到抽象算法是一个层层递进的过程。就好比命令模式中的顾客,服务员和厨师的职责,作为老板(即设计师)的你需要规划好各自的职责范围,既要防止越俎代庖,也要防止互相推诿。

你可能感兴趣的:(综合,php,PHP学习历程)