单一职责原则(SRP:single responsibility principle)
定义:一个类或者模块应该有且只有一个改变的原因,通俗的讲就是一个类只能拥有一个职责。
实例:比如一个类同时拥有A和B两个职责,当需要对A职责进行修改时,可能由于莫须有的原因导致B功能出现问题。所以这里就需要将类分解为A和B两个类。
我们程序开发中的登陆类,用户类都是一个大的单一职责。程序员都明白要写出一个高内聚低耦合的程序,但是由于我们的开发水平或者业务需求的变更,B职责又细分出B1、B2职责,这就是所谓的职责扩散。
虽然会违背单一职责,但是我们遇到这种问题通常是在B类中就地分解B1、B2的职责。这样做无可厚非,但是需要考虑是否会出现B3、B4... 到那时再去分解职责,代价昂贵。
下面将通过程序深入理解 职责扩散 后的处理方式:
这是一个鸟的类,和鸟飞行的实现。
class bird { public function fly($birdName) { echo $birdName . " can fly!"; } }
class client { $birdObj = new bird(); $birdObj->fly('鹰'); $birdObj->fly('麻雀'); $birdObj->fly('企鹅'); }
企鹅也属于鸟类,当我们调用方法时,发现企鹅是不能飞的。这时候我们可以在代码级别和方法级别做弥补。
//代码级别的弥补 class bird { public function fly($birdName) { if($birdName == '企鹅'){ echo $birdName . "can't fly!"; } else { echo $birdName . " can fly!"; } } } //方法级别的弥补(企鹅调用notFly方法) class bird { //会飞的鸟类 public function fly($birdName) { echo $birdName . " can fly!"; } //不会飞的鸟类 public function notFly($birdName) { echo $birdName . " can't fly!"; } }
代码级开小灶式的修复方法,相信大家就算想不到也能闻到其中的坏味道,当企鹅再细分为帝企鹅、王企鹅,这里只能妥协是的继续修改,而且说不定还改出鹰不能飞的结果。
而方法级的修改,可以避免此问题,只有类中方法少的时候是比较适用的,类足够大时,这就是方法级别的开小灶了。
单一职责原则的优点:
上面的问题用代码级的解决方式,是可以接收的,但是如果能够预测到以后每个动物都需要复杂的表现时,可以考虑将bird 作为基类,提供所有鸟类共同的方法,飞行的行为作为interface接口实现。