软件架构设计原则--单一职责原则

2022-12-02 10:20:10 浏览数 (1)

本专栏内容参考自:咕泡学院Tom老师的《Spring5核心原理与30个类手写实战》,仅作个人学习记录使用,如有侵权,联系速删

  单一职责(Single responsibility principle,SRP)是指不要存在多于一个导致类变更的原因。   假设我们有一个类负责两个职责,一旦需求发生变更,修改其中一个职责的逻辑代码,有可能导致另一个职责的功能发生故障。这样一来,这个类就存在两个导致类变更的原因。我们需要将这两个职责用两个类来实现,进行解耦。以达到后期需求变更维护时互相互不影响的结果。   这样设计,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更所带来的危险。总体来说就是,一个类、接口、或方法,只负责一项职责;   接下来,以课程举例:   我们的课程有直播课和录播课。直播课不能快进快退,录播课可以反复观看。先创建一个课程类Course:

代码语言:javascript复制
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";
    }

  修改之后,我们会发现,以后再给这两个需求添加别的逻辑,开发起来逻辑清晰,维护起来也容易。

  我们在实际开发种,会有项目依赖、组合、聚合这些关系,还有项目的规模,周期,技术人员的水平,对进度的把控,很多类都不符合单一职责原则。   但是,我们在编写代码的过程中,尽可能的让接口和方法保持单一职责,对项目后期的维护是又很大帮助的。

0 人点赞