单一职责原则(Single Responsibility Principle)
参考书籍:Spring5核心原理与30个类手写实战
- 基本概述:是指不要存在多于一个导致类变更的原因。假如我们有一个类负责两项职责,一旦发生需求变更需要修改其中一项职责的逻辑代码,有可能导致另一项职责的功能发生故障。这样一来这个类就存在两项导致类变更的原因。解决这个问题的办法就是将两个职责使用两个类来实现,进行解耦。后期的需求变更维护时互不影响。单一职责原则的好处是可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低需求变更时引起的风险。总体来说,就是一个类、接口或者方法只负责一项职责(具体使用根据业务拆分)。
- 从类的角度看单一职责原则
/**
* 课程类
* 功能职责一:直播课不能快进和快退
* 功能职责二:录播课可以反复的任意观看
* 普通写法
*/
public class Course {
public void study(String courseName) {
if ("直播课".equals(courseName)) {
System.out.println(courseName + "不能快进");
} else {
System.out.println(courseName + "可以反复回看");
}
}
}
/**
* 调用代码检验结果
*/
public class Check {
public static void main(String[] args) {
Course course = new Course();
course.study("直播课");
course.study("录播课");
}
}
直播课不能快进
录播课可以反复回看
- 假如此时需求发生变更,课程需要加密,两种课程的加密逻辑不同,必须修改代码,而修改代码的逻辑势必会相互影响,容易带来不可控的风险。我们需要对原来的代码进行解耦。
/**
* 直播课程
*/
public class LiveCourse {
public void study(String courseName) {
System.out.println(courseName + "不能快进看");
}
}
/**
* 录播课程
*/
public class ReplayCourse {
public void study(String courseName) {
System.out.println(courseName + "可以反复回看");
}
}
/**
* 调用代码检验结果
*/
public class Check {
public static void main(String[] args) {
LiveCourse liveCourse = new LiveCourse();
liveCourse.study("直播课");
ReplayCourse replayCourse = new ReplayCourse();
replayCourse.study("录播课");
}
}
直播课不能快进看
录播课可以反复回看
- 从接口的角度看单一职责原则
- 假如需求发生更改,课程要做权限功能。没有付费的学员只能获取课程基本信息,已经付费的学员可以获得视频流进行学习即拥有学习权限。
/**
* 课程顶层接口,包含课程的所有功能
* 获取课程名称
* 获取视频流
* 学习课程
*/
public interface ICourse {
String getCourseName();
byte[] getCourseVideo();
void studyCourse();
}
- 使用单一职责原则根据业务拆分接口,此时课程至少要有两项职责,一项是展示课程信息的职责,另一项是管理课程的职责。
/**
* 展示课程信息
* 获取课程名称
* 获取视频流
*/
public interface ICourseInfo {
String getCourseName();
byte[] getCourseVideo();
}
/**
* 管理课程
* 学习课程
*/
public interface ICourseManager {
void studyCourse();
}
- 从方法的角度看单一职责原则
- 假如需求变更需要修改学员信息
/**
* 修改用户信息
*/
public class UserInfo {
public void modify(String userName, String address, String ...info){
userName = "Tom";
address = "ShangHai";
}
}
- modify方法负责修改学员的全部信息,使得该方法承担多项职责,我们需要把方法进行拆分。
/**
* 修改用户信息
*/
public class UserInfo {
public void modifyUserName(String userName) {
userName = "Tom";
}
public void modifyAddress(String address) {
address = "ShangHai";
}
}
- 总的来说,我们在编写代码的时候尽量遵守单一职责原则,在类、接口、方法层面我们需要根据具体业务进行拆分,目的都是为了解耦合从而降低类的复杂度,提高类的可读性,提高系统的可维护性,降低需求变更时引起的风险。