本专栏内容参考自:咕泡学院Tom老师的《Spring5核心原理与30个类手写实战》,仅作个人学习记录使用,如有侵权,联系速删
单一职责(Single responsibility principle,SRP)是指不要存在多于一个导致类变更的原因。
假设我们有一个类负责两个职责,一旦需求发生变更,修改其中一个职责的逻辑代码,有可能导致另一个职责的功能发生故障。这样一来,这个类就存在两个导致类变更的原因。我们需要将这两个职责用两个类来实现,进行解耦。以达到后期需求变更维护时互相互不影响的结果。
这样设计,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更所带来的危险。总体来说就是,一个类、接口、或方法,只负责一项职责;
接下来,以课程举例:
我们的课程有直播课和录播课。直播课不能快进快退,录播课可以反复观看。先创建一个课程类Course:
public class Course {
public void study(String courseName){
if(courseName.equals("直播课")){
System.out.println(courseName "不能快进快退");
}else {
System.out.println(courseName "可以反复观看");
}
}
}
看的调用代码:
代码语言:javascript复制public class Main {
public static void main(String[] args) {
Course course = new Course();
course.study("直播课");
course.study("录播课");
}
}
从上面的代码来看,Course类承担了两种业务逻辑。假如现在要对课程进行加密处理,直播课程和录播课程从的加密逻辑不一样,必须修改代码。而根据以上的写法,修改代码的逻辑势必会相互影响,容易带来不可控的风险。我们对职责进行解耦,来看代码,分别创建两个类:LiveCourse和ReplayCourse.
代码语言:javascript复制public class LiveCourse {
public void study(String courseName){
System.out.println(courseName "不能快进快退");
}
}
代码语言:javascript复制public class ReplayCourse {
public void study(String courseName){
System.out.println(courseName "可以反复看");
}
}
看调用:
代码语言:javascript复制public static void main(String[] args) {
LiveCourse liveCourse = new LiveCourse();
liveCourse.study("直播课");
ReplayCourse replayCourse = new ReplayCourse();
replayCourse.study("录播课");
}
现在,业务继续发展,课程要做权限。没有付费的学院可以获取课程基本信息,已经付费的学院可以获取视频流,即学习权限。那么在控制课程层面上至少要有两个职责:展示和管理。我们把这两个职责分离开来,都是先同一个抽象依赖。 设计一个顶层接口,ICourse:
代码语言:javascript复制public interface ICourse {
//获取基本信息
String getCourseName();
//获取视频流
byte[] getCourseVideo();
//学习课程
void studyCourse();
//退款
void refundCourse();
}
但是根据我们之前学过的,这个接口管理的职责过多了,我们不妨把它拆分一下 ICourseInfo和ICourseManager.
代码语言:javascript复制public interface ICourseInfo {
//获取基本信息
String getCourseName();
//获取视频流
byte[] getCourseVideo();
}
代码语言:javascript复制public interface ICourseManager {
//学习课程
void studyCourse();
//退款
void refundCourse();
}
接下来,业务又拓展了,用户想要修改用户的信息,比如用户名和地址; 省劲的办法是一个方法即可完成需求:
代码语言:javascript复制 private void modifyUserInfo(String userName,String address){
userName = "Tom";
address = "北京";
}
但是我们已经学过了单一设计原则,就不要这样懒省劲了, 应当用两个方法来处理这两种需求:
代码语言:javascript复制 private void modifyName(String userName){
userName = "Tom";
}
private void modifyAddress(String address){
address = "Tom";
}
修改之后,我们会发现,以后再给这两个需求添加别的逻辑,开发起来逻辑清晰,维护起来也容易。
我们在实际开发种,会有项目依赖、组合、聚合这些关系,还有项目的规模,周期,技术人员的水平,对进度的把控,很多类都不符合单一职责原则。 但是,我们在编写代码的过程中,尽可能的让接口和方法保持单一职责,对项目后期的维护是又很大帮助的。