一、认识责任链模式
责任链模式定义:为请求创建了一个接受者对象的链。为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
该模式又叫职责链模式。
结构:
抽象处理者:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
具体处理者:实现抽象处理者的处理方法,该处理方法中会进行判断能够处理本次请求,如果可以则将请求转给其后继者继续执行处理方法。
结构图如下:
优缺点:
优点:请求的发送者和接受者解耦;可以控制执行顺序;符合开闭原则和单一职责原则。
缺点:对比较长的职责链,请求处理可能会涉及多个处理对象,性能会受到影响;增加了客户端的复杂性,可能会造成循环调用。
应用场景:
Tomcat中的过滤器链使用到了责任链模式,其中ApplicationFilterChain类实现了FilterChain接口,其底层实现使用的是数组,关键方式是doFilter()及internalDoFilter()方法。
二、实现责任链模式
该案例是在学习视频案例之后手敲了一下,视频:2020年最详细的23种Java设计模式完整视频教程全集
demo见xyz.changlu.chain包下代码:
请求对象:Request
//实例对象:通过其中属性来判定其中的执行是否有效 public class Request { private boolean requestFrequency;//请求频率 private boolean loginAuthentication;//登陆认证 private boolean accessPermission;//访问权限 public Request(RequestBuilder builder){ this.requestFrequency = builder.requestFrequency; this.loginAuthentication = builder.loginAuthentication; this.accessPermission = builder.accessPermission; } static class RequestBuilder{ private boolean requestFrequency;//请求频率 private boolean loginAuthentication;//登陆认证 private boolean accessPermission;//访问权限 public RequestBuilder setRequestFrequency(boolean requestFrequency){ this.requestFrequency = requestFrequency; return this; } public RequestBuilder setLoginAuthentication(boolean loginAuthentication){ this.loginAuthentication = loginAuthentication; return this; } public RequestBuilder setAccessPermission(boolean accessPermission){ this.accessPermission = accessPermission; return this; } public Request build(){ return new Request(this); } } public boolean isRequestFrequency() { return requestFrequency; } public boolean isLoginAuthentication() { return loginAuthentication; } public boolean isAccessPermission() { return accessPermission; } }
内部使用到了建造者模式来方便进行赋值操作!
抽象处理者:Handler
//抽象处理者 public abstract class Handler { private Handler next; public Handler(Handler handler){ this.next = handler; } public Handler getNext() { return next; } public void setNext(Handler next) { this.next = next; } abstract boolean process(Request request); }
包含了具体方法以及抽象方法,该类实际上是使用链表进行连接的,其抽象方法是留给对应的子类来进行实现其中的执行过程。
具体处理者1:RequestFrequencyHandler
//具体处理者1:请求频率处理器 public class RequestFrequencyHandler extends Handler{ public RequestFrequencyHandler(Handler handler) { super(handler); } @Override boolean process(Request request) { System.out.println("开始执行请求频率...."); //1、判断请求频率是否符合规则 if(request.isRequestFrequency()){ System.out.println("执行请求频率正常,通过!"); Handler handler = this.getNext(); //表示通过 if (handler != null) { //2、执行其下一个处理器(登陆验证) if (!handler.process(request)) { return false; } } return true; } //请求频率过多失败 System.out.println("请求频率过多失败!"); return false; } }
具体处理者2:LoginAuthenticationHandler
//登陆认证处理器 public class LoginAuthenticationHandler extends Handler{ public LoginAuthenticationHandler(Handler handler) { super(handler); } @Override boolean process(Request request) { System.out.println("开始执行登陆验证...."); //1、判断登陆验证是否通过 if(request.isLoginAuthentication()){ System.out.println("登陆验证通过!"); Handler handler = this.getNext(); //判断是否有下个执行器(本案例无) if (handler != null) { //2、判断是下个执行器是否通过(本案例是不会执行到这里的) if (!handler.process(request)) { return false; } } return true; } //登陆认证失败 System.out.println("登陆认证失败!"); return false; } }
与处理者1大致相同,也包含了执行其关联的下一个执行器。
测试程序:测试类Customer
①测试两个false情况
//测试类 public class Customer { public static void main(String[] args) { //设置request对象的属性 Request request = new Request.RequestBuilder().setRequestFrequency(false).setLoginAuthentication(false).build(); //将登陆认证执行放置到请求频率执行器之后 RequestFrequencyHandler requestFrequencyHandler = new RequestFrequencyHandler(new LoginAuthenticationHandler(null)); //开始执行 requestFrequencyHandler.process(request); } }
②测试两个true请求
说明:可以看到按照设置执行器顺序依次执行下去(就像一个链条一样),一旦有个执行方法不通过则会直接结束。
总结
责任链模式通常使用于如处理的是单个请求需要有多个请求处理者来处理不同的事情,将多个处理者链接起来。处理者可通过继承一个抽象类来实现其中的处理方法,并且若是其中情况成立可执行下一个请求处理者,形成一个执行链。