Responsibility chain model

In real life, it is a common scene that an event needs to be processed by multiple objects. For example, purchase approval process, leave process, etc. When the company's employees ask for leave, the leaders who can approve the leave include department heads, deputy general managers, general managers, etc., but the number of days each leader can approve is different. Employees must find different leaders to sign according to the number of days they need to ask for leave, that is to say, employees must remember the name, telephone number, address and other information of each leader, which undoubtedly increases the difficulty.

There are also related examples in computer software and hardware, such as datagram transmission in bus network. Each computer determines whether to receive according to whether the target address is the same as its own address; In addition, in exception handling, the handler decides whether to handle the exception according to the type of exception; And Struts2 Interceptors JSP And Servlet All these can be realized by using the responsibility chain pattern.

Definition and characteristics of pattern

Definition of Chain of Responsibility mode: in order to avoid coupling the request sender with multiple request handlers, all request handlers are connected into a chain by remembering the reference of the next object through the previous object; when a request occurs, the request can be passed along the chain until an object processes it.

Note: responsibility chain mode is also called responsibility chain mode.

In the responsibility chain mode, the customer only needs to send the request to the responsibility chain, and does not need to care about the processing details of the request and the transmission process of the request. The request will be transmitted automatically. Therefore, the responsibility chain decouples the sender of the request from the handler of the request.

The responsibility chain model is an object behavior model, and its main advantages are as follows.

  1. Reduces the coupling between objects. This mode makes an object do not need to know which object handles its request and the structure of the chain, and the sender and receiver do not need to have each other's clear information.
  2. It enhances the scalability of the system. New request processing classes can be added as needed to meet the opening and closing principle.
  3. Increased flexibility in assigning responsibilities to objects. When the workflow changes, you can dynamically change the members in the chain or transfer their order, or dynamically add or delete responsibilities.
  4. The chain of responsibility simplifies the connection between objects. Each object only needs to maintain a reference to its successor without maintaining the references of all other processors, which avoids the use of many if or if ·· else statements.
  5. Responsibility sharing. Each class only needs to deal with its own work that should be handled, and the work that should not be handled should be transferred to the next object for completion. The scope of responsibility of each class should be defined and in line with the principle of single responsibility of the class.


Its main disadvantages are as follows.

  1. There is no guarantee that every request will be processed. Since a request has no specific receiver, it cannot be guaranteed that it will be processed. The request may not be processed until it reaches the end of the chain.
  2. For a long responsibility chain, the processing of requests may involve multiple processing objects, and the system performance will be affected to some extent.
  3. The rationality of the establishment of responsibility chain depends on the client, which increases the complexity of the client, and may lead to system errors due to the wrong setting of responsibility chain, such as circular call.

Structure and implementation of pattern

In general, the responsibility chain mode can be implemented through the data link list data structure.

1. Structure of the model

The responsibility chain model mainly includes the following roles.

  1. Abstract Handler role: define an interface for processing requests, including abstract processing methods and a subsequent connection.
  2. Concrete Handler role: implement the processing method of the abstract handler to judge whether the request can be processed. If the request can be processed, process it. Otherwise, transfer the request to its successor.
  3. Client role: create a processing chain and submit a request to the specific handler object of the chain head. It does not care about the processing details and the transmission process of the request.


The essence of responsibility chain mode is to decouple request and processing, so that requests can be transmitted and processed in the processing chain; Understanding the responsibility chain model should understand its model, not its specific implementation. The unique feature of the responsibility chain model is that it combines its node processors into a chain structure, and allows the node to decide whether to process or forward the request, which is equivalent to making the request flow.

Its structure is shown in Figure 1. The client can set the responsibility chain as shown in Figure 2.

 

Abstract method:

public abstract class ChainHandler {

    protected ChainHandler chainHandler;

    public ChainHandler getSccuessive() {
        return chainHandler;
    }
    public void setSccuessive(ChainHandler sccuessive) {
        this.chainHandler = sccuessive;
    }

    public abstract void processChain(Float discount);

}

salesman:

public class Saler extends ChainHandler{

    @Override
    public void processChain(Float discount) {
        if(discount <= 0.1){
            System.out.println(this.getClass().getName() + " : " + discount);
        }else{
            chainHandler.processChain(discount);
        }
    }
}

Sales Manager:

public class Manager extends ChainHandler{

    @Override
    public void processChain(Float discount) {
        if(discount <= 0.2){
            System.out.println(this.getClass().getName() + " : " + discount);
        }else{
            chainHandler.processChain(discount);
        }
    }
}

Sales Supervisor:

public class Director extends ChainHandler{

    @Override
    public void processChain(Float discount) {
        if(discount <= 0.3){
            System.out.println(this.getClass().getName() + " : " + discount);
        }else{
            chainHandler.processChain(discount);
        }
    }
}

Vice president of sales:

public class VicePresident extends ChainHandler{

    @Override
    public void processChain(Float discount) {
        if(discount <= 0.4){
            System.out.println(this.getClass().getName() + " : " + discount);
        }else{
            chainHandler.processChain(discount);
        }
    }
}

CEO:

public class CEO extends ChainHandler{

    @Override
    public void processChain(Float discount) {
        if(discount <= 0.5){
            System.out.println(this.getClass().getName() + " : " + discount);
        }else{
            System.out.println(this.getClass().getName() + " refused : " + discount);
        }
    }
}

Create a responsibility chain using the factory model:

public class ChainFactory {

    // Create a chain of responsibility
    public static ChainHandler createHandler(){
        ChainHandler sale = new Saler();
        ChainHandler manager = new Manager();
        ChainHandler director = new Director();
        ChainHandler vicePre = new VicePresident();
        ChainHandler ceo = new CEO();

        sale.setSccuessive(manager);
        manager.setSccuessive(director);
        director.setSccuessive(vicePre);
        vicePre.setSccuessive(ceo);

        return sale;
    }
}

Client responsibility chain call:

public class Client {

    private ChainHandler chainHandler;

    public void setChainHandler(ChainHandler chainHandler) {
        this.chainHandler = chainHandler;
    }

    public void requestDiscount(Float discount){
        chainHandler.processChain(discount);
    }

    public static void main(String[] args){
        // Create a chain of responsibility
        Client client = new Client();

        client.setChainHandler(ChainFactory.createHandler());
        Random random = new Random();

        for(int i=1;i<=100;i++){
            System.out.print(i + " : ");
            client.requestDiscount(random.nextFloat());
        }
    }
}

Keywords: Algorithm

Added by TWD on Mon, 03 Jan 2022 12:37:03 +0200