首页 > 编程笔记 > Java笔记

使用单一职责原则解决实际问题

本节介绍如何使用单一职责原则解决问题。

例如,在 新宝库中,用户分为普通用户和VIP用户。普通用户不能阅读学习收费文章,VIP用户可以任意反复阅读,功能职责不一样。

首先创建用户类 User。
package net.biancheng.c.srp;

public class User {
    public void study(String userType) {
        if ("common".equals(userType)) {
            System.out.println("不能阅读收费文章");
        } else {
            System.out.println("可以任意反复阅读收费文章");
        }
    }
}
下面编写客户端测试代码,无论是普通用户还是VIP会员,都调用 study() 方法的逻辑。
public static void main(String[] args) {
    User user = new User();
    user.study("common");
    user.study("vip");
}
从上面代码看,User 类承担了两种处理逻辑。假如现在对用户进行加密,那么普通用户和VIP会员的加密逻辑是不一样的,必须修改代码。而修改代码逻辑势必会相互影响,容易带来不可控的风险。

下面我们对职责进行分离解耦,分别创建 CommonUser 和 VipUser。

CommonUser 类的代码如下。
package net.biancheng.c.srp;

public class CommonUser {
    public void study(String userType) {
        System.out.println(userType + "不能阅读收费文章");
    }
}
VipUser 类的代码如下。
package net.biancheng.c.srp;

public class VipUser {
    public void study(String userType) {
        System.out.println(userType + "任意阅读收费文章");
    }
}
客户端代码如下,将普通会员的处理逻辑调用 CommonUser 类,VIP 会员的处理逻辑调用 VipUser 类。
public static void main(String[] args) {
    CommonUser commonUser = new CommonUser();
    commonUser.study("common");

    VipUser vipUser = new VipUser();
    vipUser.study("vip");
}
对于教程方面,我们要对教程做权限。普通学员只能获得教程的基本信息,VIP 用户可以获得阅读权限。所以在控制教程层面,至少有两个职责,我们可以把展示职责和管理职责分离开,都实现同一个抽象依赖。

设计一个顶层接口 Course。
package net.biancheng.c.srp;

public interface Course {
    //获取教程的基本信息
    String getCourseTitle();

    //获得阅读权限
    byte[] getReadPow();

    //学习教程
    void studyCourse();

    //退款
    void refundCourse();
}
这里可以把 Course 接口拆分成两个接口,创建一个接口 CourseInfo 和 CourseManager。

CourseInfo 接口的代码如下。
package net.biancheng.c.srp;

public interface CourseInfo {
    //获取教程的基本信息
    String getCourseTitle();

    //获得阅读权限
    byte[] getReadPow();
}
CourseManager 接口的代码如下。
package net.biancheng.c.srp;

public interface CourseManager {

    //学习教程
    void studyCourse();

    //退款
    void refundCourse();
}
类图如下:

UML类图
下面来看方法层面的单一职责设计。有时候,我们通常会把一个方法写成下面这样。
private void modifyUserInfo(String userName, String url) {
    userName = "新宝库";
    url = "https://www.xinbaoku.com/";
}
或者是这样。
private void modifyUserInfo(String userName, String pwd, String url) {
    userName = "新宝库";
    pwd = "123456";
    url = "https://www.xinbaoku.com/";
}
显然上面两种写法的 modifyUserInfo() 方法都承担了多个职责,既可以修改 userName,也可以修改 url,甚至更多,但是这样设计明显不符合单一职责原则,我们做出如下修改,把这个方法拆成两个。
private void modifyUserName(String userName) {
    userName = "新宝库"
}

private void modifyUrl(String url) {
    url = "https://www.xinbaoku.com/"
}
代码在修改之后,开发和维护都会变得更加简单和容易。在实际项目中,代码会存在依赖、组合、聚合关系,在项目开发过程中还会受到项目的规模、周期、技术人员水平、对进度把控的影响,导致很多类都不能满足单一职责原则。但是,我们在编写代码的过程中,应尽可能地让接口和方法保持单一职责,这样对项目后期的维护是有很大帮助的。

所有教程

优秀文章