单一职责原则(SRP:Single responsibility principle)又称单一功能原则,面向对象五个基本原则(SOLID)之一。它规定一个类应该只有一个发生变化的原因。该原则由罗伯特·C·马丁(Robert C. Martin)于《敏捷软件开发:原则、模式与实践》一书中给出的。马丁表示此原则是基于汤姆·狄马克(Tom DeMarco)和Meilir Page-Jones的著作中的内聚性原则发展出的。
所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。
通过订阅哪吒专栏的场景说明一下。
1、普通用户,一般只能查阅哪吒的普通文章,并通过超链的形式时刻提醒着它们,要购买哪吒的付费专栏,付费知识就是香。
2、专属用户,通过购买专栏的形式查阅单一专栏的优质文章,并时刻提醒着,要购买其它专栏啊,毕竟学习才是王道。
3、VIP用户(订阅了哪吒的全部专栏),既可以看《Java基础教程系列》,也可以看《Spring Boot 进阶实战》,无推广,告别CRUD,进阶高级Java工程师,升职加薪,迎娶白富美。
下面根据需求场景直接编码,根据不同用户,判断阅读权限。
package com.guor.config;
public class AppConfig {
public static final String USER_GENERAL = "普通用户";
public static final String USER_EXCLUSIVE = "专属用户";
public static final String USER_VIP = "VIP用户";
}
package com.guor.designprinciples;
import com.guor.config.AppConfig;
public class UserService {
public void readByType(String userType){
if(AppConfig.USER_GENERAL.equals(userType)){
System.out.println("可以查阅哪吒的普通文章");
}else if(AppConfig.USER_EXCLUSIVE.equals(userType)){
System.out.println("可以查阅哪吒的Java基础教程系列文章");
}else if(AppConfig.USER_VIP.equals(userType)){
System.out.println("可以查阅哪吒的全部优质文章,告别CRUD,进阶高级Java工程师,升职加薪,迎娶白富美");
}
}
}
这么简单,so seay!commit,提交,下班!
第二天,经理来找我,要增加一个需求,逢年过节的要给哪吒VIP发放福利,比如赠送精美图书,赠送精美周边等。
看起来也很简单,只要增加一个ifesle就完事了,不过,作为一个高级Java开发工程师,写了一堆ifelse,不会脸红吗?
public static void main(String[] args) {
UserService userService = new UserService();
userService.readByType(AppConfig.USER_GENERAL);
userService.readByType(AppConfig.USER_EXCLUSIVE);
userService.readByType(AppConfig.USER_VIP);
}
因为UserService中通过一个ifelse实现逻辑,所以调用的时候所有用户都通过一个方法实现,对于简单的或者不用再改变的功能来说,也还可以。如果再增加其它需求,每一次需求的实现都可能影响到其他逻辑,给整个接口服务带来不可控的风险,因为代码只要修改了,就应该测试一下,对吧!
为了满足经理不但迭代的需求,不能使用一个类把所有的用户行为混为一谈,而是需要提供一个上层的接口类,对不同的用户给出单独的实现类,明确各自的职责边界,确定一个类的单一职责。
定义要实现的功能,阅读文章、推广选择。
package com.guor.service;
public interface IUserService {
// 阅读文章
void read();
// 推广宣传
void promote();
}
package com.guor.service.impl;
import com.guor.service.IUserService;
/**
* 普通用户
*/
public class GeneralUserServiceImpl implements IUserService {
public void read() {
System.out.println("可以查阅哪吒的普通文章");
}
public void promote() {
System.out.println("并通过超链的形式时刻提醒着它们,要购买哪吒的付费专栏,付费知识就是香");
}
}
package com.guor.service.impl;
import com.guor.service.IUserService;
/**
* 专属用户
*/
public class ExclusiveUserServiceImpl implements IUserService {
public void read() {
System.out.println("通过购买专栏的形式查阅单一专栏的优质文章");
}
public void promote() {
System.out.println("并通过超链的形式时刻提醒着它们,购买哪吒的其它付费专栏,付费知识就是香");
}
}
package com.guor.service.impl;
import com.guor.service.IUserService;
/**
* VIP用户
*/
public class VipUserServiceImpl implements IUserService {
public void read() {
System.out.println("脚踩风火轮,手拿乾坤圈,学习哪吒优质文章,我命由我不由天。");
}
public void promote() {
System.out.println("告别CRUD,进阶高级Java工程师,升职加薪,迎娶白富美");
}
}
每种用户对应的阅读权限都有对应的实现类,不会相互干扰。当某一类用户需要添加新的权限或增加新的用户类别时,操作起来也非常方便。比如上文中提到的逢年过节的要给哪吒VIP发放福利,比如赠送精美图书,赠送精美周边等。
通过利用单一职责原则优化后,现在每个类只负责自己的用户行为,后续无论扩展新的功能还是增加用户种类,都可以很方便的开发和维护。
在项目开发的过程中,尽可能保证接口的定义、类的实现保持单一职责,对项目后期的迭代和维护会有很大的帮助。