单一职责原则是面向对象设计原则中的一条
举个简单的例子,假设,在工厂中,一款产品从无到有需要经过10种机器。我们是让10个人,每个人拿着原材料从第一台操作到第十台比较快,还是每个机器有一个单独的人专门处理这台机器比较快。答案是显而易见的。
因此工厂在实现分工后,效率有了大幅度的提高。这就是企业管理中的分工,而在面向对象设计里,它被叫做单一职责原则(Single Pesponsibility Principle, SRP)。
在《敏捷软件开发》中,把“职责”定义为“变化的原因”,也就是说,一个类应该只有一个引起他变化的原因。这是一个最简单,最容易理解,但是却最不容易做到的一个设计原则。说的简单一点,就是怎样设计类以及类的方法界定的问题。这种问题是很普遍的,例如在MVC的框架汇中,很多人疑惑对于表单插入数据库字段过滤与安全检查应该放在M层还是C层处理,这类问题就可以归到单一职责的范围。
再比如在职员类中,将工程师、销售人员、销售经理等等都放在职员类里考虑,其结果将会非常混乱。在这个假设下,职员类里的每个方法(例如发工资)都要用if else 判断是那种职员类型,从类结构上来说会十分臃肿,并且任何职员类型,不论哪一种发生需求变化,都会改变职员类,这是我们不愿意看到的。
从上面的描述中可以看出,单一职责有两个含义:一个是避免相同的职责分散到不同的类中,另一个是避免一个类承担太多的职责。
为什么要遵守单一职责原则呢?
(1)可以减少类之间的耦合
(2)提高类的复用性
以数据持久层为例,所谓的数据持久层就是指数据库操作。如果是一个复杂的系统,那么就可能涉及到多种数据库的相互读写等,这时就需要数据持久层支持多种数据库。那应该怎么做呢?定义多个操作类吗?想法很接近了,在进一步,就是工厂模式。
单一职责原则不只是对类设计有意义,对以模块、子系统为单位的系统架构设计同样有意义。
模块、子系统也应该仅有一个引起他变化的原因,如MVC所倡导的各个层之间的互相分离其实就是单一职责原则在系统总体设计中的应用。
下面的图是CI框架的流程图
单一职责原则是最简单的原则,也是最难做好的原则。我们很自然的将职责连接在一起,所以找到并且分开这些职责是软件设计需要达到的目的。
一些简单应该遵循的做法是:
- 根据业务流程,把业务对象提炼出来。
如果业务链路太过复杂,那么将业务对象分离为多个单一业务对象。当业务链标准化后,对业务对象的内部情况做进一步处理。把第一次标准化视为最高层抽象,第二次视为次高层抽象,以此类推,直到“恰如其分”的设计层次。 - 职责的分类要注意。
有业务职责,还要有脱离业务的抽象职责,从认识业务到抽象算法是一个层层递进的过程。就好比命令模式中的顾客,服务员和厨师的职责,作为设计师的你需要提前规划好各自的职责,既要防止越俎代庖,也要防止互相推诿。