SPR全称
SRP , Single Responsibility Principle 单一职责原则
定义
一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。即一个类只做一类事
优点
- 降低类的复杂度
- 提供类的可读性,提高系统的可维护性
- 变更引起的风险降低
- 降低耦合度
实现
问题由来: 类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。
解决方案: 遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。
案例:
用一个类来描述动物的呼吸
class Animal {
public void breathe(String name){
System.out.println(name + "呼吸空气");
}
}
public class SRPClient {
public static void main(String[] args) {
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("马");
}
}
允许结果:
牛呼吸空气
马呼吸空气
如果此时又加了一种动物"鱼",由于鱼呼吸水,导致代码修改,以下几种修改方式:
方式一:添加新方法
class Animal {
public void breathe(String name){
System.out.println(name + "呼吸空气");
}
public void water(String name){
System.out.println(name + "呼吸水");
}
}
public class SRPClient {
public static void main(String[] args) {
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("马");
animal.water("鱼");
}
}
运行结果:
牛呼吸空气
马呼吸空气
鱼呼吸水
此种方案,在类级别上违背了单一职责原则,但在方法级别上却是符合单一职责原则的,并没有改动原来的方法
方式二:在原方法修改
class Animal {
public void breathe(String name) {
if ("鱼".equals(name)) {
System.out.println(name + "呼吸水");
} else {
System.out.println(name + "呼吸空气");
}
}
}
public class SRPClient {
public static void main(String[] args) {
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("马");
animal.breathe("鱼");
}
}
运行结果:
牛呼吸空气
马呼吸空气
鱼呼吸水
此种方案,直接修改Animal类开销较小,但违背了单一职责原则
方式三:建立新类
class Terrestrial {
public void breathe(String name) {
System.out.println(name + "呼吸空气");
}
}
class Aquatic {
public void breathe(String name) {
System.out.println(name + "呼吸水");
}
}
public class SRPClient {
public static void main(String[] args) {
Terrestrial terrestrial = new Terrestrial();
terrestrial.breathe("牛");
terrestrial.breathe("马");
Aquatic aquatic = new Aquatic();
aquatic.breathe("鱼");
}
}
运行结果:
牛呼吸空气
马呼吸空气
鱼呼吸水
此方案需要新增类,修改客户端,开销还是很大的。
上述三种方案各有其优缺点,根据实际情况来确定。
总结
- 只有逻辑足够简单,才可以在代码级别上违反单一职责原则
- 只有类中方法数量足够少,才可以在方法级别上违反单一职责原则