第15章 责任链模式【Chain of Responsibility Pattern】
责任链模式是将链中的每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象,当一个请求从链式的首端发出时,会沿着链的路径一次传递给每一个节点对象,直至有节点处理这个请求为止。属于行为模式。
责任链模式基本介绍
责任链模式是将链中的每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象,当一个请求从链式的首端发出时,会沿着链的路径一次传递给每一个节点对象,直至有节点处理这个请求为止。属于行为模式
责任链模式类图
从类图可以看到,责任链模式主要包含两种角色
- 抽象处理者(Handler):定义一个请求处理的方法,并维护一个下一个处理节点Handler对象的引用;
- 具体处理者(ConcreteHandler):对请求进行处理,如果不感兴趣,则进行转发
责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解的是其模式(道)而不是其具体实现(术),责任链模式的独到之处是其将节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动了起来。
责任链模式案例
我们利用责任链模式完成一个登录案例,在这个案例中我们将会对数据进行层层拦截校验
代码如下:
public class Member {
private String loginName;
private String loginPass;
private String roleName;
public Member(String loginName, String loginPass) {
this.loginName = loginName;
this.loginPass = loginPass;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getLoginPass() {
return loginPass;
}
public void setLoginPass(String loginPass) {
this.loginPass = loginPass;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
/**
* 抽象类,定义请求处理方法,并且维护下一个节点
*/
public abstract class Handler {
protected Handler chain;
public void next(Handler handler) {
this.chain = handler;
}
public abstract void doHandler(Member member);
}
/**
* 用户名密码校验
*/
public class ValidateHandler extends Handler{
@Override
public void doHandler(Member member) {
if(member.getLoginName() == null || member.getLoginPass() == null){
System.out.println("用户名密码为空");
return;
}
System.out.println("用户名密码校验成功,可以往下执行");
chain.doHandler(member);
}
}
/**
* 登录
*/
public class LoginHandler extends Handler{
@Override
public void doHandler(Member member) {
System.out.println("登录成功");
member.setRoleName("管理员");
chain.doHandler(member);
}
}
/**
* 角色权限校验
*/
public class AuthHandler extends Handler{
@Override
public void doHandler(Member member) {
if(!"管理员".equals(member.getRoleName())){
System.out.println("您不是管理员不允许操作");
return;
}
System.out.println("您是管理员,允许操作");
}
}
/**
* 将前面定义好的Handler,串联起来,形成一条链
*/
public class MemberService {
public void login(String loginName,String loginPass){
Handler validateHandler = new ValidateHandler();
Handler loginHandler = new LoginHandler();
Handler authHandler = new AuthHandler();
validateHandler.next(loginHandler);
loginHandler.next(authHandler);
Member member = new Member(loginName,loginPass);
validateHandler.doHandler(member);
}
}
/**
* 客户端代码测试
*/
public class Test {
public static void main(String[] args) {
MemberService memberService = new MemberService();
memberService.login("tom","666");
}
}
结果:
用户名密码校验成功,可以往下执行
登录成功
您是管理员,允许操作
其实我们平时使用的很多权限校验框架都是运用这样一个原理的
责任链模式和建造者模式结合使用
从上面的代码中我们可以看到负责组装链式结构的角色是MemberService,但是如果链式结构比较长的话,MemberService就会显得很臃肿,且后续更改处理者时,MemberService都要变动,不符合开闭原则。所以对这种复杂结构的创建,我们可以使用建造者模式,我们完全可以将节点对象进行自动的链式组装。客户只需要指定处理节点对象,以及对象的顺序即可。
我们来改造一下Handler的代码
/**
* 抽象类,定义请求处理方法,并且维护下一个节点
*/
public abstract class Handler<T> {
protected Handler chain;
private void next(Handler handler) {
this.chain = handler;
}
public abstract void doHandler(Member member);
public static class Builder<T>{
private Handler<T> head;
private Handler<T> tail;
public Builder<T> addHandler(Handler<T> handler){
if(this.head == null){
this.head = this.tail = handler;
return this;
}
this.tail.next(handler);
this.tail = handler;
return this;
}
public Handler<T> build() {
return this.head;
}
}
}
MemberServcice 也需要修改一下
/**
* 将前面定义好的Handler,串联起来,形成一条链
*/
public class MemberService {
public void login(String loginName,String loginPass){
Handler.Builder builder = new Handler.Builder();
builder.addHandler(new ValidateHandler())
.addHandler(new LoginHandler())
.addHandler(new AuthHandler());
Member member = new Member(loginName,loginPass);
builder.build().doHandler(member);
}
}
责任链模式在源码中的体现
SpringMVC-HandlerExecutionChain类使用了责任链模式,他的主要负责的是请求拦截器的执行和请求处理,但是他本身不处理请求,只是将请求分配给链上注册处理器执行,这是职责链实现方式,减少职责链本身与处理逻辑之间的耦合,规范了处理流程。HandlerExecutionChain 维护了 HandlerInterceptor 的集合, 可以向其中注册相应的拦截器
更多推荐
所有评论(0)