责任链模式(Chain of Responsibility Pattern)
Posted 顧棟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了责任链模式(Chain of Responsibility Pattern)相关的知识,希望对你有一定的参考价值。
责任链模式(Chain of Responsibility Pattern)
责任链模式的定义
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链模式的优点
- 责任链模式非常显著的优点是将请求和处理分开
- 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
- 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
责任链模式的缺点
- 一是性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。
- 二是调试不很方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
责任链模式的结构
职责链模式主要包含以下角色。
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
责任链模式的实现
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;
}
}
/**
* 模拟审核服务
* 1. auth 审核流程
* 2. queryAuthInfo 查询审核信息(时间)
*/
public class AuthService {
private static Map<String, Date> authMap = new ConcurrentHashMap<String, Date>();
public static Date queryAuthInfo(String uId, String orderId) {
return authMap.get(uId.concat(orderId));
}
public static void auth(String uId, String orderId) {
authMap.put(uId.concat(orderId), new Date());
}
}
public abstract class AuthLink {
/**
* 时间格式化
*/
protected SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 级别人员ID
*/
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 (null == date) {
return new AuthInfo("0001", "单号:", orderId, " 状态:待一级审批负责人 ", levelUserName);
}
AuthLink next = super.next();
if (null == 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("2021-06-14 00:00:00");
private Date endDate = f.parse("2022-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 (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 Level3AuthLink extends AuthLink {
private Date beginDate = f.parse("2020-06-01 00:00:00");
private Date endDate = f.parse("2021-06-25 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 static void main(String[] args) throws ParseException {
AuthLink authLink = new Level3AuthLink("1000013", "3级审核人")
.appendNext(new Level2AuthLink("1000012", "2级审核人")
.appendNext(new Level1AuthLink("1000011", "1级审核人")));
System.out.println("测试结果:" + JSON.toJSONString(authLink.doAuth("小哥", "1000998004813441", new Date())));
// 模拟三级负责人审批
AuthService.auth("1000013", "1000998004813441");
System.out.println("模拟三级负责人审批,测试结果:" + JSON.toJSONString(authLink.doAuth("小哥", "1000998004813441", new Date())));
// 模拟二级负责人审批
AuthService.auth("1000012", "1000998004813441");
System.out.println("模拟二级负责人审批,测试结果:" + JSON.toJSONString(authLink.doAuth("小哥", "1000998004813441", new Date())));
// 模拟一级负责人审批
AuthService.auth("1000011", "1000998004813441");
System.out.println("模拟一级负责人审批,测试结果:" + JSON.toJSONString(authLink.doAuth("小哥", "1000998004813441", new Date())));
}
责任链模式的适用场景
- 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
- 可动态指定一组对象处理请求,或添加新的处理者。
- 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。
注意事项
链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个
最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免
无意识地破坏系统性能。
本文主要参考:
- 小傅哥的《重学Java模式》
- 《C语言中文网》设计模式的相关内容
- 《设计模式之禅》第二版 秦小波
以上是关于责任链模式(Chain of Responsibility Pattern)的主要内容,如果未能解决你的问题,请参考以下文章
责任链模式(Chain of Responsibility)
15-责任链(Chain of Responsibility)模式Ruby实现
责任链模式(Chain of Responsibility Pattern)
责任链模式(chain of responsibility)