单一职责原则

单一职责(Simple Responsiblity Principle,SRP)是指不要存在多余一个导致类变更的原因。假设我们有一个Class负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能会导致另外一个职责发生故障。这样一来,这个Class存在两个导致类变更的原因。要解决这种问题,我们就要给两个职责用两个Class来实现,进行解耦,后期需求变更维护互不影响。总体来说就是一个Class/Interface/Method只负责一项职责。
接下来,我们来看代码实例,以网课为例,我们的课程有直播课和录播课。直播课不能快进和快退,录播课可以任意的反复观看,功能职责不一样。先创建一个Course类:

package com.framework.single;

public class Course {
    public void study(String courseName) {
        if ("直播课".equalsIgnoreCase(courseName)) {
            System.out.println(courseName + ",不能快进快退!");
        } else {
            System.out.println(courseName + ",可以反复观看!");
        }
    }
}

看代码调用:

package com.framework.single;

public class UnitTest {
    public static void main(String[] args) {
        Course course = new Course();
        course.study("直播课");
        course.study("录播课");
    }
}

从上面代码来看,Course类承担了两种处理逻辑。假如,现在要对课程进行加密,那么直播课和录播课的加密逻辑都不一样,必须要修改代码。而修改逻辑代码势必会相互影响容易造成不可控的风险。我们对职责进行分离解耦,分别创建两个类ReplayCourse和LiveCourse:

package com.framework.single;

public class LiveCourse {
    public void study(String courseName) {
        System.out.println(courseName + ",不能快进快退!");
    }
}
package com.framework.single;

public class ReplayCourse {
    public void study(String courseName) {
        System.out.println(courseName + ",可以反复看 !");
    }
}

调用代码:

package com.framework.single;

public class UnitTest {
    public static void main(String[] args) {
        LiveCourse liveCourse = new LiveCourse();
        liveCourse.study("直播课");
        ReplayCourse replayCourse = new ReplayCourse();
        replayCourse.study("录播课");
    }
}

业务继续发展,课程要做权限。没有付费的学员可以获取课程基本信息,已经付费的学员可以获取视频流,即学习权限。那么对于控制课程层面上至少有两个职责。我们可以把展示职责和管理职责分离开来,都实现同一个抽象依赖。设计一个顶层接口,创建ICourse接口:

package com.framework.single;

public interface ICourse {
    //获取基本信息
    String getCourseName();

    //获取视频流
    byte[] getCourseVideo();

    //学习课程
    void studyCourse();

    //退款
    void refundCourse();
}

我们可以把这个接口拆成两个接口:

package com.framework.single;

public interface ICourseInfo {
    String getCourseName();

    byte[] getCourseVideo();
}
package com.framework.single;

public interface ICourseManager {
    void studyCourse();

    void refundCourse();
}

来看一下类图:
微信截图_20200825140021.png
下面我们来看一下方法层面的单一职责设计。有时候,我们为了偷懒,通常会把一个方法写成下面这样:

    private void modifyUserInfo(String userName,String address){
        userName = "Tom";
        address = "Wuhan";
    }

显然,方法中承担了多个职责,既可以修改userName又可以修改address,甚至更多,明显不符合单一职责。我们可以修改,把方法拆开,一个方法只修改一个变量。我们实际开发中,会项目依赖、组合、聚合这些关系,还有项目的规模、周期、技术人员的水平,对进度的把控,很多类都不符合单一职责原则。但是我们在编写代码的过程,应尽可能让接口和方法保持单一职责,这对我们项目的后期维护是有很大帮助的。