责任链模式
比如一个web请求,有一堆的过滤器需要处理(或不处理)这个请求,而这一堆接收此次请求的过滤器对象形成一条调用链,即为责任链模式
- 定义:为请求创建一个接收此次请求对象的链
- 类型:行为型
- 适用场景:一个请求的处理需要多个对象当中的一个或几个协作处理
- 优点:
- 请求的发送者和接收者(请求的处理)解耦
- 责任链可以动态组合
- 缺点:
- 责任链太长或者处理时间过长,影响性能
- 责任链有可能过多
- 相关设计模式
- 责任链模式和状态模式:责任链模式当中各个对象并不指定下一个处理的对象者是谁,只有在客户端来设定链条中的顺序以及元素,直到被某个元素处理,或者整个链条结束,状态模式是让每个状态模式知道自己下一个处理的对象是谁,也就是说在编译时就设定好了,这个是他俩最大的区别。
Coding
public class Course { private String name; private String article; private String video; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getArticle() { return article; } public void setArticle(String article) { this.article = article; } public String getVideo() { return video; } public void setVideo(String video) { this.video = video; } @Override public String toString() { return "Course{" + "name='" + name + '\'' + ", article='" + article + '\'' + ", video='" + video + '\'' + '}'; } } public abstract class Approver { protected Approver approver; public void setNextApprover(Approver approver) { this.approver = approver; } public abstract void deploy(Course course); } public class ArticleApprover extends Approver { @Override public void deploy(Course course) { if (course.getArticle() != null) { System.out.println(course.getName() + "含有手记,批准"); if (approver != null) { approver.deploy(course); } } else { System.out.println(course.getName() + "不含有手记,不批准,流程结束"); } } } public class VideoApprover extends Approver { @Override public void deploy(Course course) { if (course.getVideo() != null) { System.out.println(course.getName() + "含有视频,批准"); if (approver != null) { approver.deploy(course); } } else { System.out.println(course.getName() + "不含有视频,不批准,流程结束"); } } }
测试
public class Test { public static void main(String[] args) { Approver articleApprover = new ArticleApprover(); Approver videoApprover = new VideoApprover(); Course course = new Course(); course.setName("Java设计模式"); course.setArticle("Java设计模式的手记"); course.setVideo("Java设计模式的视频"); articleApprover.setNextApprover(videoApprover); articleApprover.deploy(course); } } =======输出====== Java设计模式含有手记,批准 Java设计模式含有视频,批准 // 将 course.setVideo("Java设计模式的视频"); 注释后,打印结果: Java设计模式含有手记,批准 Java设计模式不含有视频,不批准,流程结束
UML
说明:其实类图也很简单,两个 Approver 类继承了其抽象类,Course 是课程主题,最重要的方法就是抽象类 Approver,责任链的核心就是 Approver 类里面包含一个自己同样类型的对象,一般设为 protected,用于子类继承。
源码中的应用
- javax.servlet.Filter:重点看它的doFilter方法,看看它有个传参FilterChain,随便找一个它下面的实现类MockFilterChain,可以看到它的doFilter方法里面调用了下一个Filter的doFilter方法。
public interface Filter { void init(FilterConfig var1) throws ServletException; void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; void destroy(); } public interface FilterChain { void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException; } public class MockFilterChain implements FilterChain { private final List<Filter> filters; ... public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { Assert.notNull(request, "Request must not be null"); Assert.notNull(response, "Response must not be null"); if (this.request != null) { throw new IllegalStateException("This FilterChain has already been called!"); } else { if (this.iterator == null) { this.iterator = this.filters.iterator(); } if (this.iterator.hasNext()) { Filter nextFilter = (Filter)this.iterator.next(); nextFilter.doFilter(request, response, this); } this.request = request; this.response = response; } } ... }
- 在 SpringSecurity 中所有的过滤器形成的调用链就是用的是责任链模式