Responsibility chain model (case analysis)

1, Concept

1. Understanding the responsibility chain model

The responsibility chain mode is an object behavior mode. The responsibility chain mode is actually a mode of processing requests. It gives multiple processors (object nodes) the opportunity to process the requests. After the requests are processed step by step through this processing chain. Output the final product output.

2. Example of responsibility chain pattern in JDK

Let's take a look at the example of the responsibility chain pattern in JDK, and then we will continue to implement the real example of this pattern. We know that we can have multiple catch blocks in the try catch block code. Here, each catch block is the processor that handles this particular exception.

Therefore, when any exception occurs in the try block, it is sent to the first catch block for processing. If the catch block cannot handle it, it forwards the request to the next object in the chain, the next catch block. If even the last catch block cannot handle it, the exception will be thrown and linked to the caller.

3. Use of responsibility chain mode

How to use the responsibility chain model?

  • An interface or abstract class
  • Differentiated processing of each object
  • Object chain (array) initialization (concatenation)

2, Example demonstration

When a request is processed by the project, we can perform 1) non null parameter check, 2) security call verification, 3) verification of blacklist, 4) rule interception objects. These are a chain of responsibility.

According to the above instructions and rules, build the corresponding classes for demonstration.

1. An interface or abstract class

This interface or abstract class requires:

  • There is a property that points to the next object
  • A set method that sets the next object
  • The method of differentiated implementation for subclass objects (such as the doFilter method of the following code)
/**
  * @Description: Define an interface or abstract class
  */
public abstract class AbstractHandler {

    /**
     * The next object in the responsibility chain
     */
    private AbstractHandler nextHandler;
    
    // Specific parameters intercept logic and implement it for subclasses
    public void filter(HttpServletRequest request, HttpServletResponse response) {
        //Execute current chain
        doFilter(request, response);
        //If there is a next chain, execute the next chain
        if (getNextHandler() != null) {
            getNextHandler().filter(request, response);
        }
    }

    //Get next chain object
    public AbstractHandler getNextHandler() {
        return nextHandler;
    }
    
    //Insert the next object in the responsibility chain
    public void setNextHandler(AbstractHandler nextHandler){
        this.nextHandler = nextHandler;
    }

    abstract void doFilter(HttpServletRequest request, HttpServletResponse response);
}

2. Differentiated processing of each object

In the responsibility chain, the differentiated processing of each object, such as the business scenario in this section, includes parameter verification object, security verification object, blacklist verification object and rule interception object.

/**
 * 1,Parameter verification object
 **/
@Component
@Order(1) //Ranked first in order, verified first
public class CheckParamFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("1,Non null parameter check");
    }
}

/**
 *  2,Security verification object
 */
@Component
@Order(2) //The verification sequence is the second
public class CheckSecurityFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        //invoke Security check
        System.out.println("2,Security call verification");
    }
}

/**
 *  3,Blacklist verification object
 */
@Component
@Order(3) //The verification sequence is the third
public class CheckBlackFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        //invoke black list check
        System.out.println("3,Verification blacklist");
    }
}

/**
 *  4,Rule intercept object
 */
@Component
@Order(4) //The verification sequence is No. 4
public class CheckRuleFilterObject extends AbstractHandler {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response) {
        //check rule
        System.out.println("4,Rule intercept object");
    }
}

3 object chaining (initialization)

/**
  * @Description: Object chaining (initializing) objects
  */
@Component("ChainPatternDemo")
public class ChainPatternDemo {

    //Automatically inject objects into each responsibility chain
    @Autowired
    private List<AbstractHandler> abstractHandleList;

    private AbstractHandler abstractHandler;

    //spring is automatically executed after injection, and the objects of the responsibility chain are connected
    @PostConstruct
    public void initializeChainFilter(){

        for(int i = 0;i<abstractHandleList.size();i++){
            if(i == 0){
                //Because @ Order(1) has taken order above, the first is the non empty parameter check
                abstractHandler = abstractHandleList.get(0);
            }else{
                AbstractHandler currentHander = abstractHandleList.get(i - 1);
                AbstractHandler nextHander = abstractHandleList.get(i);
                currentHander.setNextHandler(nextHander);
            }
        }
    }

    //Directly call this method to return the last processed response
    public HttpServletResponse exec(HttpServletRequest request, HttpServletResponse response) {
        //Here, abstractHandler is the first one, and then it will go down one by one
        abstractHandler.filter(request, response);
        return response;
    }
}

4. Use demo

@RestController
public class PayController {

    @Autowired
    private ChainPatternDemo chainPatternDemo;

    @RequestMapping("/testHandler")
    public  void testHandler(HttpServletRequest req, HttpServletResponse resp){
        //Call responsibility chain
        chainPatternDemo.exec(req,resp);
    }
}

Operation results

1,Non null parameter check
2,Security call verification
3,Verification blacklist
4,Rule intercept object

Perfect!

In conclusion, when an object needs to be processed many times in development, we can consider using the responsibility chain design pattern. The above example can also be used in actual development.


reference resources

1,Actual combat! What design patterns are commonly used in work Thank you.



Added by moe on Thu, 28 Oct 2021 19:28:15 +0300