设计模式--设计原则--单一职责原则

78 阅读4分钟

定义

单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP。这个原则的英文描述是这样的:A class or module should have a single responsibility。如果我们把它翻译成中文,那就是:一个类或者模块只负责完成一个职责(或者功能)

单一职责原则的定义描述非常简单,也不难理解。一个类只负责完成一个职责或者功能。也就是说,不要设计大而全的类,要设计粒度小、功能单一的类。换个角度来讲就是,一个类包含了两个或者两个以上业务不相干的功能,那我们就说它职责不够单一,应该将它拆分成多个功能更加单一、粒度更细的类。

模拟案例

需求说明

在当前视频网站看视频时,网站针对不同的用户类型,给予不同的服务

访客用户:一般只可以观看480P视频,并时刻提醒注册会员可以观看高清视频。

普通会员:可以观看720P视频,但有广告。

VIP会员:既可以观看1080P视频,又可以关闭或跳过广告。

违背原则方案

/**
 * @description:单一职责-模拟场景一般实现
 * @version: 1.0
 * @Author blackcat
 */
public class VideoUserService {

    public void serviceGrade(String userType) {

        if ("VIP会员".equals(userType)) {
             System.out.println("VIP会员,视频1080P 蓝光");
        } else if ("普通会员".equals(userType)) {
            System.out.println("普通会员,视频720P 超清");
        } else if ("访客用户".equals(userType)) {
            System.out.println("访客用户,视频480P 高清");
        }
    }

    //测试
    public static void main(String[] args) {
        VideoUserService service = new VideoUserService();
        service.serviceGrade("VIP会员");
        service.serviceGrade("普通会员");
        service.serviceGrade("访客用户");
    }
}

这一个类里包含了多个不同的行为,拥有多种用户职责。如果继续在类上添加逻辑和拓展功能会显得非常臃肿。如果是几乎不需要迭代的功能,这样的实现也未尝不可。但是面对频繁迭代的业务需求,这样的代码就很难支撑系统迭代,每一次的需求实现会影响其他逻辑,对整个服务有不可控的风险。

单一职责改善代码

设计模式-单一原则.drawio.png

定义接口

/**
 * @description:用户视频服务接口
 * @version: 1.0
 * @Author blackcat
 */
public interface IVideoUserService {

    /**
     * 视频清晰的:480、720、1080
     */
    void definition();

    /**
     * 有无广告
     */
    void advertisement();
}

实现类

实现类:访客用户

/**
 * @description:访客用户视频服务实现类
 * @version: 1.0
 * @Author blackcat
 */
public class GuestVideoUserService implements IVideoUserService {

    @Override
    public void definition() {
        System.out.println("访客用户,视频480P 高清");
    }

    @Override
    public void advertisement() {
        System.out.println("访客用户,视频有广告");
    }
}

实现类:普通会员

/**
 * @description:普通会员视频服务实现类
 * @version: 1.0
 * @Author blackcat
 */
public class OrdinaryVideoUserService implements IVideoUserService {
    @Override
    public void definition() {
        System.out.println("普通会员,视频720P 超清");
    }

    @Override
    public void advertisement() {
        System.out.println("普通会员,视频有广告");
    }
}

实现类:VIP会员

/**
 * @description:VIP会员视频服务实现类
 * @version: 1.0
 * @create 2022/3/13 14:17
 * @Author blackcat
 */
public class VipVideoUserService implements IVideoUserService {
    @Override
    public void definition() {
        System.out.println("VIP会员,视频1080P 蓝光");
    }

    @Override
    public void advertisement() {
        System.out.println("VIP会员,视频无广告");
    }
}

4.测试


/**
 *
 * @description:单一职责-模拟场景优化后实现 spring中可用注入的方式
 * @version: 1.0
 * @Author blackcat
 */

public class VideoUserService {

    private Map<String, IVideoUserService> videoMap = new HashMap<>();

    {
        videoMap.put("访客用户", new GuestVideoUserService());
        videoMap.put("普通会员", new OrdinaryVideoUserService());
        videoMap.put("VIP会员", new VipVideoUserService());
    }


    public void serviceGrade(String userType) {
        IVideoUserService videoUserService = videoMap.get(userType);
        //TODO 空处理
        if(ObjectUtil.isNotNull(videoUserService)){
             videoUserService.definition();
        }   
    }



    //测试
    public static void main(String[] args) {
        VideoUserService service = new VideoUserService();
        service.serviceGrade("VIP会员");
        service.serviceGrade("普通会员");
        service.serviceGrade("访客用户");
    }
}

总结

职责是否单一需要根据业务具体分析进行抽象,不用过度设计,业务、周期多维度统筹

我们在网站首页可以注册, 登录, 登出等操作. 我们通常的做法是:

public interface UserOperate {

    void login(UserInfo userInfo);

    void register(UserInfo userInfo);

    void logout(UserInfo userInfo);
}


public class UserOperateImpl implements UserOperate{
    @Override
    public void login(UserInfo userInfo) {
        // 用户登录
    }

    @Override
    public void register(UserInfo userInfo) {
        // 用户注册
    }

    @Override
    public void logout(UserInfo userInfo) {
        // 用户登出
    }
}

那如果按照单一职责原则拆分, 拆分为下面的形式,这样维护的类就很多


public interface Register {
    void register();
}

public interface Login {
    void login();
}

public interface Logout {
    void logout();
}


public class RegisterImpl implements Register{

    @Override
    public void register() {

    }
}

public class LoginImpl implements Login{
    @Override
    public void login() {
        // 用户登录
    }
}

public class LogoutImpl implements Logout{

    @Override
    public void logout() {

    }
}