The Single Responsibility Principle 单一职责原则
参考http://blog.csdn.net/zhengzhb/article/details/7278174
定义:"引起类变化的因素永远不要多于一个。" 或者说 "一个类有且仅有一个职责"。
实际问题:类C负责2个不同的职责R1和R2,当R1业务变化需要修改类C时,可能会使运行正常的R2发生异常。
解决方案:将类C分割成2个类C1和C2, C1负责职责R1,C2负责R2。当R1业务变化只要修改C1即可而不会影响C2的正常运行.
职责扩散:即由于某种原因(需求变更或者程序设计者境界提高等),职责P被分化为粒度更细的职责P1和P2。
比如:类C只负责一个职责R,这样设计是符合单一职责原则的。后来由于某种原因,需要将职责R细分为粒度更细的职责R1,R2。这时如果要使程序遵循单一职责原则,需要将类C也分解为两个类C1和C2,分别负责R1、R2两个职责。 但是在程序已经写好的情况下,这样做简直太费时间了。所以简单的修改类C,用它来负责两个职责是一个比较不错的选择,虽然这样做有悖于单一职责原则。
举例说明:
class Animal{ public void breathe(String animal){ System.out.println(animal+"呼吸空气"); } } public class Client{ public static void main(String[] args){ Animal animal = new Animal(); animal.breathe("牛"); animal.breathe("羊"); animal.breathe("猪"); } }
程序上线后,发现问题了,并不是所有的动物都呼吸空气的,比如鱼就是呼吸水的。修改时如果遵循单一职责原则,需要将Animal类细分为陆生动物类Terrestrial,水生动物Aquatic,代码如下:
class Terrestrial{ public void breathe(String animal){ System.out.println(animal+"呼吸空气"); } } class Aquatic{ public void breathe(String animal){ System.out.println(animal+"呼吸水"); } } public class Client{ public static void main(String[] args){ Terrestrial terrestrial = new Terrestrial(); terrestrial.breathe("牛"); terrestrial.breathe("羊"); terrestrial.breathe("猪"); Aquatic aquatic = new Aquatic(); aquatic.breathe("鱼"); } }
我们会发现如果这样修改花销是很大的,除了将原来的类分解之外,还需要修改客户端。而直接修改类Animal来达成目的虽然违背了单一职责原则,但花销却小的多,代码如下:
class Animal{ public void breathe(String animal){ if("鱼".equals(animal)){ System.out.println(animal+"呼吸水"); }else{ System.out.println(animal+"呼吸空气"); } } } public class Client{ public static void main(String[] args){ Animal animal = new Animal(); animal.breathe("牛"); animal.breathe("羊"); animal.breathe("猪"); animal.breathe("鱼"); } }
可以看到,这种修改方式要简单的多。但是却存在着隐患:有一天需要将鱼分为呼吸淡水的鱼和呼吸海水的鱼,则又需要修改Animal类的breathe方法,而对原有代码的修改会对调用“猪”“牛”“羊”等相关功能带来风险,也许某一天你会发现程序运行的结果变为“牛呼吸水”了。这种修改方式直接在代码级别上违背了单一职责原则,虽然修改起来最简单,但隐患却是最大的。还有一种修改方式:
class Animal{ public void breathe(String animal){ System.out.println(animal+"呼吸空气"); } public void breathe2(String animal){ System.out.println(animal+"呼吸水"); } } public class Client{ public static void main(String[] args){ Animal animal = new Animal(); animal.breathe("牛"); animal.breathe("羊"); animal.breathe("猪"); animal.breathe2("鱼"); } }
可以看到,这种修改方式没有改动原来的方法,而是在类中新加了一个方法,这样虽然也违背了单一职责原则,但在方法级别上却是符合单一职责原则的,因为它并没有动原来方法的代码。这三种方式各有优缺点,那么在实际编程中,采用哪一中呢?其实这真的比较难说,需要根据实际情况来确定。我的原则是:只有逻辑足够简单,才可以在代码级别上违反单一职责原则;只有类中方法数量足够少,才可以在方法级别上违反单一职责原则;
遵循单一职责原的优点有:
原文:http://www.cnblogs.com/tonyliang/p/4303341.html