文章目录
责任链模式场景
- 责任链模式场景
- 责任链模式实战
- 不使用责任链模式的写法
- 使用责任链模式的写法
用于解决一组服务中的先后执行处理关系, 例如出差补贴, 不超过100的组内领导审批, 超过100不超过200的,先组内领导审批接着部门领导审批, 超过200不超过300 的, 从组内领导 到部门领导, 再到公司领导挨个审批.
责任链模式实战模拟上线的三级 二级 一级 审批. 平时用三级审批. 临近促销二级审批. 618, 双十一期间需要一级审批.
不使用责任链模式的写法创建模块tutorials-16.0-0 创建AuthService 审核服务
public class AuthService {
private static Map authMap = new ConcurrentHashMap();
//查询审核结果(queryAuthInfo)
public static Date queryAuthInfo(String uId, String orderId) {
return authMap.get(uId.concat(orderId));
}
//处理审核(auth)
public static void auth(String uId, String orderId) {
//由谁审核的和审核的单子ID作为唯一key值记录到内存Map结构中
authMap.put(uId.concat(orderId), new Date());
}
}
创建tutorials-16.0-1 模块 AuthController 实现审核.
public class AuthController {
private SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 时间格式化
public AuthInfo doAuth(String uId, String orderId, Date authDate) throws ParseException {
//三级审批
Date date = AuthService.queryAuthInfo("1015", orderId);
if (date == null) return new AuthInfo("0001", "单号: ", orderId, " 状态: 待三级审批负责人 ", "王工");
// 二级审批 在六月1号到25号之间的 , 需要二级审批
if (authDate.after(f.parse("2020-06-01 00:00:00")) && authDate.before(f.parse("2020-06-25 23:59:59"))){
date = AuthService.queryAuthInfo("1012", orderId);
if (date == null) return new AuthInfo("0001", "单号: ", orderId, " 状态: 待二级审批负责人 ", "张经理");
}
// 一级审批
if (authDate.after(f.parse("2020-06-11 00:00:00")) && authDate.before(f.parse("2020-06-20 23:59:59"))) {
date = AuthService.queryAuthInfo("1013", orderId);
if (null == date) return new AuthInfo("0001", "单号:", orderId, " 状态:待一级审批负责人 ", "段总");
}
return new AuthInfo("0001", "单号: ", orderId, " 状态: 审批完成");
}
}
创建测试类ApiTest
public class ApiTest {
private Logger logger = LoggerFactory.getLogger(ApiTest.class);
@Test
public void test_AuthController() throws ParseException {
AuthController authController = new AuthController();
// 模拟三级负责人审批
logger.info("测试结果: {}", JSON.toJSONString(authController.doAuth("周杰伦", "1000657570", new Date())));
logger.info("测试结果:{}", "模拟三级负责人审批,王工");
AuthService.auth("1000013", "1000998004813441");
// 模拟二级负责人审批
logger.info("测试结果: {}", JSON.toJSONString(authController.doAuth("林俊杰", "1000657570", new Date())));
logger.info("测试结果: {}", "模拟二级负责人审批,张经理");
AuthService.auth("1000013", "1000998004813441");
// 模拟一级负责人审批
logger.info("测试结果:{}", JSON.toJSONString(authController.doAuth("小傅哥", "1000998004813441", new Date())));
logger.info("测试结果:{}", "模拟一级负责人审批,段总");
AuthService.auth("1000011", "1000998004813441");
logger.info("测试结果:{}", "审批完成");
}
}
控制台打印如下 :
22:13:59.104 [main] INFO com.thc.design.ApiTest - 测试结果: {"code":"0001","info":"单号: 1000657570 状态: 待三级审批负责人 王工"}
22:13:59.107 [main] INFO com.thc.design.ApiTest - 测试结果:模拟三级负责人审批,王工
22:13:59.108 [main] INFO com.thc.design.ApiTest - 测试结果: {"code":"0001","info":"单号: 1000657570 状态: 待三级审批负责人 王工"}
22:13:59.108 [main] INFO com.thc.design.ApiTest - 测试结果: 模拟二级负责人审批,张经理
22:13:59.108 [main] INFO com.thc.design.ApiTest - 测试结果:{"code":"0001","info":"单号: 1000998004813441 状态: 待三级审批负责人 王工"}
22:13:59.108 [main] INFO com.thc.design.ApiTest - 测试结果:模拟一级负责人审批,段总
22:13:59.108 [main] INFO com.thc.design.ApiTest - 测试结果:审批完成
使用责任链模式的写法
创建tutorials-16.0-2模块 创建AuthInfo类 责任链中返回对象定义
public class AuthInfo {
private String code;
private String info = "";
public AuthInfo(String code, String ...infos) {
this.code = code;
for (String str:infos){
this.info = this.info.concat(str);
}
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
创建AuthLink类 链路抽象类定义
public abstract class AuthLink {
// 时间格式化
protected SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
protected String levelUserId;
protected String levelUserName;
private AuthLink next;
public AuthLink(String levelUserId, String levelUserName) {
this.levelUserId = levelUserId;
this.levelUserName = levelUserName;
}
public AuthLink next() {
return next;
}
public AuthLink appendNext(AuthLink next) {
this.next = next;
return this;
}
public abstract AuthInfo doAuth(String uId, String orderId, Date authDate);
}
一级审核
public class Level1AuthLink extends AuthLink {
public Level1AuthLink(String levelUserId, String levelUserName) {
super(levelUserId, levelUserName);
}
@Override
public AuthInfo doAuth(String uId, String orderId, Date authDate) {
Date date = AuthService.queryAuthInfo(levelUserId, orderId);
// 第一个审核类中会先判断是否审核通过,如果没有审核通过则返回结果给调用方,引导去审核。
// (这里简单模拟审核后 时间信息不为空,作为判断条件)
if (date == null) {
return new AuthInfo("0001", "单号: ", orderId, " 状态: 待一级审批负责人 ", levelUserName);
}
AuthLink next = super.next();
if (next == null) {
// 判断完成后获取下一个审核节点;super.next();,如果不存在下一个节点,则直接返回结果。
return new AuthInfo("0000", "单号: ", orderId, " 状态: 一级审批完成负责人", " 时间: ", f.format(date), "审批人: ", levelUserName);
}
return next.doAuth(uId, orderId, authDate);
}
}
二级审核
public class Level2AuthLink extends AuthLink {
private Date beginDate = f.parse("2020-06-11 00:00:00");
private Date endDate = f.parse("2020-06-20 23:59:59");
public Level2AuthLink(String levelUserId, String levelUserName) throws ParseException {
super(levelUserId, levelUserName);
}
@Override
public AuthInfo doAuth(String uId, String orderId, Date authDate) {
Date date = AuthService.queryAuthInfo(levelUserId, orderId);
if (date == null) {
return new AuthInfo("0001", "单号: ", orderId, " 状态: 待二级审批负责人: ", levelUserName);
}
AuthLink next = super.next();
if (null == next) {
return new AuthInfo("0000", "单号:", orderId, " 状态:二级审批完成负责人", " 时间:", f.format(date), " 审批人:", levelUserName);
}
// 之后是根据不同的业务时间段进行判断是否需要,二级和一级的审核。
if (authDate.before(beginDate) || authDate.after(endDate)) {
return new AuthInfo("0000", "单号:", orderId, " 状态:二级审批完成负责人", " 时间:", f.format(date), " 审批人:", levelUserName);
}
// 最后返回下一个审核结果;next.doAuth(uId, orderId, authDate)
return next.doAuth(uId, orderId, authDate);
}
}
三级审核.
public class Level3AuthLink extends AuthLink {
private Date beginDate = f.parse("2020-06-11 00:00:00");
private Date endDate = f.parse("2020-06-20 23:59:59");
public Level3AuthLink(String levelUserId, String levelUserName) throws ParseException {
super(levelUserId, levelUserName);
}
@Override
public AuthInfo doAuth(String uId, String orderId, Date authDate) {
Date date = AuthService.queryAuthInfo(levelUserId, orderId);
if (null == date) {
return new AuthInfo("0001", "单号: " + orderId, " 状态: 待三级审批负责人 ", levelUserName);
}
AuthLink next = super.next();
if (null == next) {
return new AuthInfo("0000", "单号:", orderId, " 状态:三级审批负责人完成", " 时间:", f.format(date), " 审批人:", levelUserName);
}
if (authDate.before(beginDate) || authDate.after(endDate)) {
return new AuthInfo("0000", "单号:", orderId, " 状态:三级审批负责人完成", " 时间:", f.format(date), " 审批人:", levelUserName);
}
return next.doAuth(uId, orderId, authDate);
}
}
测试类 :
public class ApiTest {
private Logger logger = LoggerFactory.getLogger(ApiTest.class);
@Test
public void test_AuthLink() throws ParseException {
/**
* 责任链创建,实际的业务中会包装到控制层;
* AuthLink authLink = new Level3AuthLink("1000013", "王工") .appendNext(new Level2AuthLink("1000012", "张经理") .appendNext(new Level1AuthLink("1000011", "段总")));
* 通过把不同的责任节点进行组装,构成一条完整业务的责任链。
*/
AuthLink authLink = new Level3AuthLink("1003", "王工")
.appendNext(new Level2AuthLink("1002", "张经理"))
.appendNext(new Level1AuthLink("1001", "段总"));
logger.info("测试结果: {}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));
// 模拟三级负责人审批
AuthService.auth("1003", "10000522");
logger.info("测试结果:{}", "模拟三级负责人审批,王工");
/**
* 接下里不断的执行查看审核链路authLink.doAuth(...),通过返回结果对数据进行3、2、1级负责人审核,直至最后审核全部完成。
*/
logger.info("测试结果:{}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));
// 模拟二级负责人审批
AuthService.auth("1002", "10000522");
logger.info("测试结果:{}", "模拟二级负责人审批,张经理");
logger.info("测试结果:{}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));
// 模拟一级负责人审批
AuthService.auth("1001", "10000522");
logger.info("测试结果:{}", "模拟一级负责人审批,段总");
logger.info("测试结果:{}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));
}
通过把不同的责任节点进行组装,构成一条完整业务的责任链。
AuthLink authLink = new Level3AuthLink("1003", "王工")
.appendNext(new Level2AuthLink("1002", "张经理"))
.appendNext(new Level1AuthLink("1001", "段总"));
运行后结果如下
22:32:10.860 [main] INFO com.thc.design.test.ApiTest - 测试结果: {"code":"0001","info":"单号: 10000522 状态: 待三级审批负责人 王工"}
22:32:10.864 [main] INFO com.thc.design.test.ApiTest - 测试结果:模拟三级负责人审批,王工
22:32:10.864 [main] INFO com.thc.design.test.ApiTest - 测试结果:{"code":"0000","info":"单号:10000522 状态:三级审批负责人完成 时间:2022-03-28 22:32:10 审批人:王工"}
22:32:10.864 [main] INFO com.thc.design.test.ApiTest - 测试结果:模拟二级负责人审批,张经理
22:32:10.864 [main] INFO com.thc.design.test.ApiTest - 测试结果:{"code":"0000","info":"单号:10000522 状态:三级审批负责人完成 时间:2022-03-28 22:32:10 审批人:王工"}
22:32:10.864 [main] INFO com.thc.design.test.ApiTest - 测试结果:模拟一级负责人审批,段总
22:32:10.864 [main] INFO com.thc.design.test.ApiTest - 测试结果:{"code":"0000","info":"单号:10000522 状态:三级审批负责人完成 时间:2022-03-28 22:32:10 审批人:王工"}