1、单一职责原则
定义:不能存在多余一个导致类变更的原因,通俗的说,即一个类只负责一项职责。
问题由来:类T负责两个不同的职责:职责P1、职责P2。当由于职责P1需求发生改变而修改T时,有可能造成原本运行正常的职责P2发生故障。
解决方案:遵循单一职责原则,分别建立两个类T1、T2分别来完成职责P1、P2,这样在修改P1时,不会影响到P2。
注意:类T负责职责P,假设在某一天职责P细化成了P1、P2,那么在单一职责原则的指引下,我们需要建立两个类T1、T2,但是有时候发现在程序写好的情况下,这么改会浪费时间,所以简单的修改T,使他同时负责两个职责也是不错的选择,虽然这样做违背了单一职责原则。但是如果某天P细化成了P3、P4、P5。。。。。Pn呢?所以,在职责扩散到我们无法控制的程度之前,立刻对代码进行重构。
举例:
用一个类来描述动物呼吸的场景
class Animal{
public void breathe(String animal){
System。out。println(animal+"呼吸空气");
}
}
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 beathe(String animal){
System。out。println(animal+"呼吸水");
}
}
class client_{
public static void main(String[] args){
Terrestrial terrestrial = new Terrestrial();
terrestrial。breathe("牛");
terrestrial。breathe("羊");
terrestrial。breathe("猪");
Aquatic quatic = new Aquatic();
quatic。beathe("鱼");
}
}
这样修改花销很大,除了将原来的类Animal分解之外,还需要修改客户端。而直接修改Animal类虽然违背了单一职责原则,但是花销很小,代码如下:
class Animal_{
public void beathe(String animal){
if("鱼"。equals(animal)){
System。out。println(animal+"呼吸水");
}else{
System。out。println(animal+"呼吸空气");
}
}
}
这样做client只需要加一句animal。breathe(“鱼”)这样做很简单,但是存在很大的隐患。如果哪一天鱼要分为淡水鱼和呼吸海水的海水鱼,那么又要修改animal的breathe方法,而对于这个修改可能会对调用猪牛羊的也造成风选,也许哪一天变成 猪牛羊也呼吸水了,这种修改方式违背了单一职责原则,虽然改起来简单那,但是隐患很大
还有一种修改方式
class Animal__{
public void beathe1(String animal){
System。out。println(animal+"呼吸空气");
}
public void beathe2(String animal){
System。out。println(animal+"呼吸水");
}
}
这样修改了 只需要在client加一句animal。breathe2(“鱼”),虽然这样也违背了单一职责原则,但是在方法级别上是符合 单一职责原则的,因为并没有动原有的方法的代码。这三种都各有优缺点,但是在实际中采用哪一种还真是比较难说。 原则是:只有逻辑足够简单,才可以在代码级别上违反单一职责原则;只有类中方法足够少,才能在方法级别上违反单一职责原则 。
上面的例子,因为它很简单,所以无论在代码级别上还是方法级别上违反了单一职责原则,都不会造成太大的影响。但是在实际应用中的类都要负责的多,一旦发生职责扩散而需要修改类时,除非这个类本身非常简单,否则还是要遵循单一职责原则的好!
下面总结单一职责原则的优点:
1、可以降低类的负责度,一个类只负责一个职责,其逻辑肯定要比负责多项职责的简单的多
2、提高类的可读性,提高系统的可维护性
3、变更引起的风险降低,变更时必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响
4、需要说明一点的是单一职责原则不只是对面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责原则