Responsibility chain mode (responsibility chain mode)

Posted by navinj on Thu, 10 Feb 2022 02:48:04 +0100

 

1. OA system procurement approval requirements

Procurement approval project of school OA system (procurement of teaching equipment by purchasers): the demand is

  1. If the amount is less than or equal to 5000, it shall be approved by the teaching Director (0 < = x < = 5000)
  2. If the amount is less than or equal to 10000, it shall be approved by the president (5000 < = x < = 10000)
  3. If the amount is less than or equal to 30000, it shall be approved by the vice president (10000 < = x < = 30000)
  4. If the amount exceeds 30000, it shall be approved by the president (30000 < x)

2. Traditional solution OA system approval

2.1 traditional design scheme (class diagram)

The traditional solution to OA system approval adopts if else.

2.2 analysis of traditional solutions for OA system approval

Analysis of traditional solutions to OA system approval

  1. The traditional method is to call the corresponding Approver to complete the approval according to the purchase amount after receiving a purchase request.
  2. Traditional problem analysis: the client will use branch judgment (such as switch) to process different purchase requests, so there are the following problems: (1) if the approval amount of personnel at all levels changes, it also needs to change at the client; (2) the client must clearly know how many approval levels and accesses there are
  3. In this way, there is a strong coupling between the processing of a purchase request and the Approver, which is not conducive to code expansion and maintenance
  4. Solution = responsibility chain model

3. Basic introduction of responsibility chain mode

3.1 basic introduction

3.2 schematic diagram of responsibility chain mode

4. The responsibility chain mode solves the procurement approval of OA system

4.1 # train of thought analysis and illustration (class diagram)

4.2} code implementation

/**
 * Request class
 */
public class PurchaseRequest {
    /**
     * Request type
     */
    private int type = 0;
    /**
     * Requested amount
     */
    private float price = 0.0f;
	/**
	 * 
	 */
	private int id = 0;
    //constructor 
    public PurchaseRequest(int type, float price, int id) {
        this.type = type;
        this.price = price;
        this.id = id;
    }
    public int getType() {return type;}
    public float getPrice() {return price;}
    public int getId() {return id;}
}
public abstract class Approver {
    /**
     * Next processor
     */
    Approver approver;
    /**
     * Name (handler)
     */
    String name;
    public Approver(String name) {
        this.name = name;
    }
    /**
     * Set next processor
     *
     * @param approver Next processor
     */
    public void setApprover(Approver approver) {
        this.approver = approver;
    }
    /**
     * The method of processing the approval request obtains a request. The processing is completed by subclasses, so the method is made abstract
     *
     * @param purchaseRequest Request class
     */
    public abstract void processRequest(PurchaseRequest purchaseRequest);
}
public class DepartmentApprover extends Approver {
    public DepartmentApprover(String name) {
        super(name);
    }
    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() <= 5000) {
            System.out.println(" Request number id= " + purchaseRequest.getId() + " cover " + this.name + " handle");
        } else {
            approver.processRequest(purchaseRequest);
        }
    }
}

public class CollegeApprover extends Approver {
    public CollegeApprover(String name) {
        super(name);
    }
    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000) {
            System.out.println(" Request number id= " + purchaseRequest.getId() + " cover " + this.name + " handle");
        } else {
            approver.processRequest(purchaseRequest);
        }
    }
}

public class ViceSchoolMasterApprover extends Approver {
    public ViceSchoolMasterApprover(String name) {
        super(name);
    }
    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000) {
            System.out.println(" Request number id= " + purchaseRequest.getId() + " cover " + this.name + " handle");
        } else {
            approver.processRequest(purchaseRequest);
        }
    }
}

public class SchoolMasterApprover extends Approver {
    public SchoolMasterApprover(String name) {
        super(name);
    }
    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() > 30000) {
            System.out.println(" Request number id= " + purchaseRequest.getId() + " cover " + this.name + " handle");
        } else {
            approver.processRequest(purchaseRequest);
        }
    }
}
public class Client {
    public static void main(String[] args) {
        //Create a request
        PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 1);

        //Create relevant approvers
        DepartmentApprover departmentApprover = new DepartmentApprover("Director Zhang");
        CollegeApprover collegeApprover = new CollegeApprover("President Li");
        ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("Vice Colonel Wang");
        SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("Principal Tong");

        //It is necessary to set the next of each approval level (the handler forms a ring)
        departmentApprover.setApprover(collegeApprover);
        collegeApprover.setApprover(viceSchoolMasterApprover);
        viceSchoolMasterApprover.setApprover(schoolMasterApprover);
        schoolMasterApprover.setApprover(departmentApprover);

        departmentApprover.processRequest(purchaseRequest);
        viceSchoolMasterApprover.processRequest(purchaseRequest);
    }
}
 Request number id= 1 Handled by principal Tong
 Request number id= 1 Handled by principal Tong

5 source code analysis of the application of responsibility chain pattern in spring MVC framework

org.springframework.web.servlet.DispatcherServlet#doDispatch

 

explain

  • In the flow chart of spring MVC request, the interceptor related method interceptor is executed Prehandler wait
  • When processing spring MVC requests, we use the responsibility chain pattern and the adapter pattern
  • HandlerExecutionChain is mainly responsible for the execution and request processing of the request interceptor, but it does not process the request itself, but only assigns the request to the registered processor on the chain for execution. This is the implementation method of the responsibility chain, reduces the coupling between the responsibility chain itself and the processing logic, and regulates the processing flow
  • HandlerExecutionChain maintains a collection of handlerinterceptors to which corresponding interceptors can be registered

6 precautions and details of responsibility chain model

  1. Separate the request and processing to realize decoupling and improve the flexibility of the system
  2. The object is simplified so that the object does not need to know the structure of the chain
  3. The performance will be affected, especially when the chain is relatively long. Therefore, it is necessary to control the maximum number of nodes in the chain. Generally, set a maximum number of nodes in the Handler and judge whether the threshold has been exceeded in the setNext() method. If the threshold is exceeded, the chain is not allowed to be established to avoid the unintentional damage to the system performance caused by the super long chain
  4. Inconvenient debugging. Similar to recursion, the logic may be complex during debugging
  5. Best application scenario: when there are multiple objects that can process the same request, such as multi-level request, leave / salary increase approval process, Tomcat Encoding processing in Java Web and interceptor

 

 

 

Topics: Design Pattern