Chain of Responsibility概述

Chain of Responsibility - 图1

玩具代码案例-一个简单的链式调用

链式处理器接口

IChainHandler

  1. package online.javabook.gof.behavioral.patterns1.chain;
  2. public abstract class IChainHandler {
  3. private IChainHandler next;
  4. public void setNext(IChainHandler next) {
  5. this.next = next;
  6. }
  7. public abstract void handle(String request);
  8. public void nextHandler(String request) {
  9. if(next != null) {
  10. next.handle(request);
  11. }
  12. }
  13. }

链式处理器实现

ChainHandler1

  1. package online.javabook.gof.behavioral.patterns1.chain;
  2. public class ChainHandler1 extends IChainHandler {
  3. @Override
  4. public void handle(String request) {
  5. System.out.println(this.getClass().getSimpleName() + ": handler " + request);
  6. nextHandler(request);
  7. }
  8. }

ChainHandler2

  1. package online.javabook.gof.behavioral.patterns1.chain;
  2. public class ChainHandler2 extends IChainHandler {
  3. @Override
  4. public void handle(String request) {
  5. System.out.println(this.getClass().getSimpleName() + ": handler " + request);
  6. nextHandler(request);
  7. }
  8. }

ChainHandler3

package online.javabook.gof.behavioral.patterns1.chain;

public class ChainHandler3 extends IChainHandler {

    @Override
    public void handle(String request) {
        System.out.println(this.getClass().getSimpleName() + ": handler " + request);

        nextHandler(request);
    }
}

链式处理器调用

Main

package online.javabook.gof.behavioral.patterns1.chain.app;

import online.javabook.gof.behavioral.patterns1.chain.ChainHandler1;
import online.javabook.gof.behavioral.patterns1.chain.ChainHandler2;
import online.javabook.gof.behavioral.patterns1.chain.ChainHandler3;
import online.javabook.gof.behavioral.patterns1.chain.IChainHandler;

public class Main {
    public static void main(String[] args) {
        IChainHandler chainHandler1 = new ChainHandler1();
        IChainHandler chainHandler2 = new ChainHandler2();
        IChainHandler chainHandler3 = new ChainHandler3();

        chainHandler1.setNext(chainHandler2);
        chainHandler2.setNext(chainHandler3);

        chainHandler1.handle("request");
    }
}

Console

ChainHandler1: handler request
ChainHandler2: handler request
ChainHandler3: handler request


现实世界中的过滤器模式

Java Web程序员在现实世界中接触的第一个过滤器模式的设计应该就是 javax.sevlets下的Filter和FilterChain。

Filter

package javax.servlet;

import java.io.IOException;

public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {
    }
}
package javax.servlet.http;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.GenericFilter;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public abstract class HttpFilter extends GenericFilter {
    public HttpFilter() {
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            this.doFilter((HttpServletRequest)req, (HttpServletResponse)res, chain);
        } else {
            throw new ServletException("non-HTTP request or response");
        }
    }

    protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(req, res);
    }
}

FilterChain

package javax.servlet;

import java.io.IOException;

public interface FilterChain {
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}
package org.springframework.mock.web;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

public class MockFilterChain implements FilterChain {
    @Nullable
    private ServletRequest request;
    @Nullable
    private ServletResponse response;
    private final List<Filter> filters;
    @Nullable
    private Iterator<Filter> iterator;

    public MockFilterChain() {
        this.filters = Collections.emptyList();
    }

    public MockFilterChain(Servlet servlet) {
        this.filters = initFilterList(servlet);
    }

    public MockFilterChain(Servlet servlet, Filter... filters) {
        Assert.notNull(filters, "filters cannot be null");
        Assert.noNullElements(filters, "filters cannot contain null values");
        this.filters = initFilterList(servlet, filters);
    }

    private static List<Filter> initFilterList(Servlet servlet, Filter... filters) {
        Filter[] allFilters = (Filter[])ObjectUtils.addObjectToArray(filters, new MockFilterChain.ServletFilterProxy(servlet));
        return Arrays.asList(allFilters);
    }

    @Nullable
    public ServletRequest getRequest() {
        return this.request;
    }

    @Nullable
    public ServletResponse getResponse() {
        return this.response;
    }

    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");
        Assert.state(this.request == null, "This FilterChain has already been called!");
        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;
    }

    public void reset() {
        this.request = null;
        this.response = null;
        this.iterator = null;
    }

    private static final class ServletFilterProxy implements Filter {
        private final Servlet delegateServlet;

        private ServletFilterProxy(Servlet servlet) {
            Assert.notNull(servlet, "servlet cannot be null");
            this.delegateServlet = servlet;
        }

        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            this.delegateServlet.service(request, response);
        }

        public void init(FilterConfig filterConfig) throws ServletException {
        }

        public void destroy() {
        }

        public String toString() {
            return this.delegateServlet.toString();
        }
    }
}