Study design patterns - chain of responsibility pattern

Chain of Responsibility pattern

A definition of Dian

   A plurality of object a chance to handle the request, thereby avoiding the coupling between the sender and receiver of the request . These objects together into a chain, and pass the request along the chain until an object handles it up . (Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.)

 

Two Dian understand

   Focus on the chain of responsibility pattern is to "chain", passes the request on the "chain", if the "node" on the "chain" is responsible for handling the request, to take responsibility, otherwise it will pass the request to the next "node" .

  Because it is processed by the object on the chain of responsibility in charge of processing the request, the consumer only need to deal with a request to the chain of responsibility, without concern for the details of processing, so that the coupling between the sender and receiver of the request.

 

Wed and Examples

  Tomcat in the realization FilterChain

  1. FilterChain Interface

    Filtered port link, i.e., the chain of responsibility object interface encapsulates processed Filter, interact with the client, the client only need to request it to handle, do not need to know the internal details.

    There are two general maintenance process implemented for Filter objects inside a array is a linked list, the FilterChain using arrays, linked lists is the Pipeline.

/**
 * 参考 javax.servlet.FilterChain
 *
 * @author TimFruit
 * @date 19-5-11 下午6:08
 */
public interface FilterChain {
    /**
     * Causes the next filter in the chain to be invoked, or if the calling
     * filter is the last filter in the chain, causes the resource at the end of
     * the chain to be invoked.
     *
     * @param request
     *            the request to pass along the chain.
     * @param response
     *            the response to pass along the chain.
     *
     */
    public void doFilter(ServletRequest request, ServletResponse response);
}

 

 

  2. Filter Interface

  Processed interfaces, the most important is doFilter (ServletRequest request, ServletResponse response, FilterChain chain) , wherein the object transfer FilterChain, for controlling whether to continue to the next recursive call Filter.

/ ** 
 * 
 * reference the javax.servlet.Filter 
 * 
 * @author TimFruit 
 * @date 19-5-11 PM 6:08 
 * / 
public  interface the Filter { 

    public  void the init (the FilterConfig FilterConfig); 

  interface method of processing true // 
    public  void the doFilter (the ServletRequest Request, the ServletResponse Response, 
                         the FilterChain catena alberghiera); 

    public  void the destroy (); 
}

 

  3. FilterConfig Interface

    Filter configuration interface, which FilterChain Tomcat's implementation is registered FilterConfig, through the initial configuration corresponding to FilterConfig Filter, in line with the principles of Demeter (the principle of least knowledge)

/**
 *
 * 参考 javax.servlet.FilterConfig
 *
 * @author TimFruit
 * @date 19-5-11 下午6:08
 */
public interface FilterConfig {

    /**
     * Get the name of the filter.
     */
    public String getFilterName();

    /**
     * Returns a <code>String</code> containing the valve of the named
     * initialization parameter, or <code>null</code> if the parameter does not
     * exist.
     *
     * @param name
     *            <code>String</code> specifying the name of the initialization
     *            parameter
     *
     * 
     
    

    
     
    

 

  4. AppFilterChain achieved, where the reference is implemented inside tomcat

/ ** 
 * @author TimFruit 
 * @date 19-5-12 AM 8:54 
 * / 
public  class AppFilterChain the implements the FilterChain { 

    // [warning] Tomcat source is an array (AppFilterConfig [])
     // used herein for convenience, Therefore, using the arrayList 
    Private List <AppFilterConfig> = appFilterConfigs new new the ArrayList <> (); 

    // identification filter chain invoked 
    Private  int POS = 0 ; 


    public AppFilterChain () { 
    } 


    public  void addAppFilterConfig (AppFilterConfig FilterConfig) { 
        appFilterConfigs.add (FilterConfig); 
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response) {
        //do other ...
        internalDoFilter(request, response);
    }

    private void internalDoFilter(ServletRequest request, ServletResponse response){
        if(pos<appFilterConfigs.size()) {
            AppFilterConfig appFilterConfig = appFilterConfigs.get(pos);
            pos++;

            Filter filter;
            try {
                filter = appFilterConfig.getFilter();
            } catch(A ClassNotFoundException | IllegalAccessException | an InstantiationException is E) {
                 the throw  new new ServletException ( "Get Filter Error" , E); 
            } 

            filter.doFilter (Request, Response, the this ); 
        } 
    } 


    / ** 
     * reuse 
     * / 
    void Reuse () { 
        POS = 0 ; 
    } 
}

 

  5. AppFilterConfig implemented, with reference to the realization tomcat

/**
 * @author TimFruit
 * @date 19-5-12 上午8:54
 */
public class AppFilterConfig implements FilterConfig{

    /**
     * 过滤器链名字
     */
    private String name;
    private Map<String,String> paramMap;
    /**
     * 过滤器的类名
     */
    private String filterClass;
    private volatile  Filter filter;


    /**
     * Empty String collection to serve as the basis for empty enumerations.
     */
    private static final List<String> emptyString = Collections.emptyList();

    public AppFilterConfig(String name, String filterClass) {
        this.name = name;
        this.filterClass=filterClass;
    }

    public AppFilterConfig(String name,String filterClass, Map<String, String> paramMap) {
        this.name = name;
        this.filterClass=filterClass;
        this.paramMap = paramMap;
    }


    // --------------------------------------- filterConfig methods
    @Override
    public String getFilterName() {
        return this.name;
    }

    @Override
    public String getInitParameter(String name) {
        if(paramMap==null){
            return null;
        }
        if(paramMap.containsKey(name)){
            return paramMap.get(name);
        }
        return null;
    }

    @Override
    public Enumeration<String> getInitParameterNames() {
        if(paramMap==null){
            return Collections.enumeration(emptyString);
        }
        return Collections.enumeration(paramMap.keySet());

    }
    // ---------------------------------------


    Filter getFilter() throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        if(filter==null){
            synchronized (AppFilterConfig.class){
                Class filterClazz=Class.forName(this.filterClass);
                Filter filter=(Filter) filterClazz.newInstance();

                filter.init(this);
                this.filter=filter;
            }
        }

        return filter;

    }


}

 

  6. Filter to achieve

/**
 *
 * @author TimFruit
 * @date 19-5-12 上午10:15
 */
public class AppendAFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        String responseStr=response.getResponse();

        if(responseStr==null){
            String requestStr=request.getRequest();
            if(requestStr==null ) { 
                requestStr = "" ; 
            } 
            responseStr = requestStr; 
        } 

        // choose to assume responsibility, the append "A" 
        responseStr responseStr + = "A" ; 
        response.setResponse (responseStr); 

        // [warning] here is to continue the call chain, is also You may choose not to continue to call 
        the chain.doFilter (Request, Response); 
    } 

    @Override 
    public  void the destroy () { 

    } 
}

 

  7. Scene class

/**
 * @author TimFruit
 * @date 19-5-12 上午10:48
 */
public class Client {
    public static void main(String[] args) {
        AppFilterChain filterChain=new AppFilterChain();

        AppFilterConfig appendAFilterConfig=new AppFilterConfig("appendAFilter", AppendAFilter.class.getName());
        filterChain.addAppFilterConfig(appendAFilterConfig); // append "A"


        Map<String,String> BFilterMap=new HashMap<>();
        BFilterMap.put(ReplaceBFilter.REPLACE_STR, "_B_"); //将"B"替换成"_B_"
        AppFilterConfig replaceBFilterConfig=new AppFilterConfig("replaceBFilter", ReplaceBFilter.class.getName(), BFilterMap);
        filterChain.addAppFilterConfig(replaceBFilterConfig);




        ServletRequest request=new SimpleRequest("ABCD");
        ServletResponse response=new SimpleResponse();

        System.out.println("request: "+request.getRequest());
        filterChain.doFilter(request, response);
        System.out.println("after filter, response: "+response.getResponse());
    }
}

  

  Test Results:

request: ABCD
after filter, response: A_B_CDA

 

  Case complete code:

  https://gitee.com/timfruit189/test-design-pattern

 

Learning materials

  <Zen design pattern> Qinxiao Bo

  Tomcat source code

 

Guess you like

Origin www.cnblogs.com/timfruit/p/10847668.html