单一职责原则
# 单一职能原则(Simple Responsibility Principle)
## 单一职责原则定义
不要存在多于一个导致类变更的原因和因素,一个类就用来做一件事情,避免一个类有多个功能。如果一个功能进行变更,修改类可能会造成其他功能的破坏;
一个类,一个方法,一个接口仅负责一个职能;
## 举个例子
从类的角度来讲,如果一个课程类Cource,课程分为直播课和录播课程两种,直播课不能重复,不能控制进度,但是录播课可以灵活调整进度,可以反复观看。在设计类的时候应该创建两个类,LiveCource和ReplayCource两个类;不要创建一个类,然后在方法中根据课程类型进行判断,在执行或者返回相应的数据;
### Course类
```java
public class Course {
public void study(String courseType){
if ("直播课".equals(courseType)){
System.err.println("不能控制进度,不能重复播放");
}
if ("录播课".equals(courseType)){
System.err.println("可以控制进度,可以重复播放");
}
}
}
```
以上的实际把两个课程揉杂在一起了,业务比较复杂的情况下,如果修改直播课程的逻辑部分时,可能会影响到录播课程的逻辑,这样是不符合单一职能原则的,此时应该创建两个类,将职能分开;
### ReplayCource类
```java
public class ReplayCource {
public void study(){
System.err.println("可以控制进度,可以重复播放");
}
}
```
### LiveCourse类
```text
public class LiveCourse {
public void study(){
System.err.println("不能控制进度,不能重复播放");
}
}
```
从接口的角度讲面来讲,一个接口可能会提供很多方法,比如设置课程权限的,还有查询课程详情的,还有观看课程,下载课程等等吧;
所以设计接口的时候不可以把所有的方法集中到一个接口中,这样显的这个接口很复杂,同时,可能有的课程根本不需要实现那些方法,比如每日一课这种形式的课程,每天10分钟,这种课程不能下载,不用付费等,所以没有必要去实现所有的接口方法;
### ICourse
```java
public interface ICourse {
void study();
void download();
void add();
void del();
}
```
以上列举了几个方法,学习和下载是用户端的方法,添加和删除是运营端的功能,所以这个可以进行一下拆分:
### IAdminCourse接口
```java
public interface IAdminCourse {
void add();
void del();
}
```
### IClientCourse接口
```text
public interface IClientCourse {
void study();
void download();
}
```
以上拆分成两个接口,具体的直播课或者录播课或者其他形式的课程可以根据自己的特点实现不同的接口了;
在方法层面上来说,一个方法可能间杂多种功能,比如查找课程,可以直接按照课程名查找,也可以按照关键字或者老师名来找,此时如果把这几种情况放到一个方法里是很糟糕的,维护性极差;
### ClientCource
```java
public class ClientCource implements ICliantCource {
@Override
public void get(String name, String tag, String teacherName) {
if (!StringUtils.isEmpty(name)){
System.err.println("按照课程名称查找");
}
if (!StringUtils.isEmpty(tag)){
System.err.println("按照课程分类查找");
}
if (!StringUtils.isEmpty(teacherName)){
System.err.println("按照课程老师查找");
}
}
}
```
以上的设计是很糟糕的,下面进行拆分:
### ICliantCource接口
```java
public interface ICliantCource {
void getByName(String name);
void getByTag(String tag);
void getByTeacher(String teacherName);
}
```
### ClientCource类
```text
public class ClientCource implements ICliantCource {
@Override
public void getByName(String name) {
System.err.println("按照课程名称查找");
}
@Override
public void getByTag(String tag) {
System.err.println("按照课程分类查找");
}
@Override
public void getByTeacher(String teacherName) {
System.err.println("按照课程老师查找");
}
}
```
## 单一职责原则优点
> 单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。
- **降低类的复杂度**:一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多;
- **提高类的可读性**:复杂性降低,自然其可读性会提高;
- **提高系统的可维护性**:可读性提高,那自然更容易维护了;
- **变更引起的风险降低**:变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响;