定义
- 将链中的每个节点看作一个对象,每个节点负责的请求都不一样,并且会自动维护下一个节点对象
- 一个请求从链的首端发出时,会沿着链的路径依次传递给每个对象,直到有对象处理这个请求为止
适用场景
- 多个对象可以处理同一请求,但具体由哪个对象处理则在运动时动态决定
- 在不明确指定接受者的情况下,向多个对象中的一个提交请求
- 可动态指定一组对象请求
实例
public abstract class Hander<T> {
protected Hander next;
protected void next(Hander hander){
this.next = hander;
}
public abstract void doHander(Member member);
public static class Builder<T> {
private Hander<T> head;
private Hander<T> tail;
public Builder<T> addHander(Hander hander) {
if (head == null) {
this.head = this.tail = hander;
return this;
}
this.tail.next(hander);
this.tail = hander;
return this;
}
public Hander<T> build() {
return this.head;
}
}
}
@Data
public class Member {
private String loginName;
private String loginPassword;
private String roleName;
private String emailName;
public Member(String loginName, String loginPassword, String emailName) {
this.loginName = loginName;
this.loginPassword = loginPassword;
this.emailName = emailName;
}
}
public class ValidateHander extends Hander {
@Override
public void doHander(Member member) {
if (StringUtils.isEmpty(member.getLoginName()) ||
StringUtils.isEmpty(member.getLoginPassword())) {
System.out.println("用户名和密码为空");
return;
}
System.out.println("用户名和密码不为空,可以往下执行");
next.doHander(member);
}
}
public class LoginHander extends Hander {
@Override
public void doHander(Member member) {
System.out.println("登录成功");
member.setRoleName("管理员");
next.doHander(member);
}
}
public class EmailHander extends Hander {
@Override
public void doHander(Member member) {
if (StringUtils.isEmpty(member.getEmailName())) {
System.out.println("你的邮箱未注册");
return;
}
System.out.println("你的邮箱已经注册,可以继续执行");
next.doHander(member);
}
}
public class AuthHander extends Hander {
@Override
public void doHander(Member member) {
if(!"管理员".equals(member.getRoleName())) {
System.out.println("你不是管理员没有操作权限");
return;
}
if(!"666".equals(member.getEmailName())) {
System.out.println("你未注册管理员邮箱没有操作权限");
return;
}
System.out.println("允许操作");
}
}
public class MemberService {
public void login(String loginName, String loginPassword, String emailName) {
Hander.Builder builder = new Hander.Builder();
builder.addHander(new ValidateHander())
.addHander(new LoginHander())
.addHander(new EmailHander())
.addHander(new AuthHander());
builder.build().doHander(new Member(loginName,loginPassword,emailName));
}
}
public class Test {
public static void main(String[] args) {
MemberService memberService = new MemberService();
memberService.login("hello","1","888");
}
}
应用
- netty Channeloutboundhander
- servlet dofilter
优点
- 将请求与处理解耦
- 请求处理者,只需要处理感兴趣的节点,不感兴趣的转发给下一个节点
- 链式传递处理请求功能,不许关注链路结构 ,只需等待处理结果
- 链路结构灵活,动态的改变链路结构新增或者删减责任
- 易于扩展新的请求处理类(节点),符合开闭原则
缺点
- 责任链太长或者处理时间长,影响整体性能
- 对象节点存在循环引用时,造成死循环,系统崩溃