定义:为请求创建一个接收此次请求对象的链,对该请求对象执行一系列的操作。
类型:行为型;
使用场景:一个请求的处理需要多个对象当中的一个或几个协作处理;
优点:
- 请求的发送者和接收者(请求的处理)解耦;
- 责任链可以动态组合;
缺点:
- 责任链太长或者处理时间过长,影响性能;
- 责任链有可能过多;
示例:
本文通过博客(Blog)发布流程中的title、author、type、content验证来模拟责任链,其中任何一个验证失败都会导致博客发布失败,UML类图如下所示:
类对应代码如下:
// Filter接口
public interface Filter {
boolean doFilter(Blog blog);
}
// Title校验
public class TitleFilter implements Filter {
public boolean doFilter(Blog blog) {
String title = blog.getTitle();
if (StringUtils.isEmpty(title)){
System.out.println("作者验证不通过,不允许发布!");
return false;
}else {
System.out.println("作者验证通过!");
return true;
}
}
}
// Author校验
public class AuthorFilter implements Filter{
public boolean doFilter(Blog blog) {
String author = blog.getAuthor();
if (StringUtils.isNotEmpty(author)){
System.out.println("标题验证通过!");
return true;
}else {
System.out.println("标题验证不通过,不允许发布!");
return false;
}
}
}
// Type校验
public class TypeFilter implements Filter{
public boolean doFilter(Blog blog) {
String type = blog.getType();
if (StringUtils.isEmpty(type)){
System.out.println("文章类别验证不通过,不允许发布");
return false;
}else {
System.out.println("文章类别验证通过");
return true;
}
}
}
// Content校验
public class ContentFilter implements Filter {
public boolean doFilter(Blog blog) {
String content = blog.getContent();
if (StringUtils.isEmpty(content)){
System.out.println("文章内容验证不通过,不允许发布!");
return false;
}else {
System.out.println("文章内容验证通过!");
return true;
}
}
}
// FilterChain
public class FilterChain implements Filter {
private List<Filter> filters = new LinkedList<Filter>();
public void add(Filter filter){
filters.add(filter);
}
public void delete(Filter filter){
filters.remove(filter);
}
public boolean doFilter(Blog blog) {
for (Filter filter : filters) {
if (!filter.doFilter(blog)){
return false;
}
}
return true;
}
}
// 测试类
public class Test {
public static void main(String[] args) {
Blog blog = new Blog("责任链模式","teihin","","责任链模式是设计模式之一");
FilterChain fc1 = new FilterChain();
fc1.add(new TitleFilter());
fc1.add(new AuthorFilter());
FilterChain fc2 = new FilterChain();
fc2.add(new TypeFilter());
fc2.add(new ContentFilter());
fc1.add(fc2);
fc1.doFilter(blog);
}
}
// 输出:
作者验证通过!
标题验证通过!
文章类别验证不通过,不允许发布!
JDK源码:
javax.servlet包下Filter和FilterChain接口以及相应的实现类,以CharacterEncodingFilter为例:
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 CharacterEncodingFilter extends OncePerRequestFilter {
private String encoding;
private boolean forceEncoding;
public CharacterEncodingFilter() {
this.forceEncoding = false;
}
public CharacterEncodingFilter(String encoding) {
this(encoding, false);
}
public CharacterEncodingFilter(String encoding, boolean forceEncoding) {
this.forceEncoding = false;
Assert.hasLength(encoding, "Encoding must not be empty");
this.encoding = encoding;
this.forceEncoding = forceEncoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public void setForceEncoding(boolean forceEncoding) {
this.forceEncoding = forceEncoding;
}
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request, response);
}
}