The responsibility chain pattern of Java design pattern

Keywords: less Spring Java Tomcat

The responsibility chain pattern of Java design pattern

 

Purchase approval project of school OA system: requirements are

Purchaser purchasing teaching equipment
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 Dean (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 is more than 30000, approved by the principal (30000 < x)



Traditional solution OA system approval, traditional design solution


1) The traditional method is to call the corresponding Approver (Approver) to complete the approval according to the purchase amount after receiving a purchase request.
2) Traditional way of 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 amount of personnel approval at each level changes, it also needs to change at the client; (2) the client must know clearly how many approval levels and access there are.
3) In this way, there is a strong coupling concern between the processing of a purchase request and the Approver, which is not conducive to the extension and maintenance of the code
4) Solution responsibility chain model



Basic introduction to responsibility chain mode

1) Chain of Responsibility Pattern, also called responsibility chain pattern, creates a chain of receiver objects for the request chain. This pattern decouples the sender and receiver of the request.
2) The responsibility chain pattern typically includes a reference to another recipient for each recipient. If an object cannot process the request, it passes the same request to the next recipient, and so on.
3) This type of design pattern belongs to behavioral pattern.

Description of schematic class diagram:
1) Handler: an abstract handler, which defines an interface for processing requests, and means another handler.
2) ConcreteHandlerA and B are the specific processors. They can handle the requests they are responsible for and access their successors (i.e. the next processor). If they can handle the current request, they will handle it. Otherwise, they will give the request to their successors to handle it, thus forming a responsibility chain.
3) Request, which contains many attributes, represents a request.






Responsibility chain mode to solve OA system procurement approval

1) Application instance requirements
Prepare procedures to complete the procurement approval project of school OA system: Requirements
Purchaser purchasing teaching equipment
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 Dean (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 is more than 30000, approved by the principal (30000 < x)
2) class diagram








package com.example.demo.responsibility;

/**
 * Request class
 * @author zhaozhaohai
 *
 */
public class PurchaseRequest {
	
	/**
	 * Request type
	 */
	private int type = 0;
	
	/**
	 * Amount requested
	 */
	private float price = 0.0f;
	
	private int id = 0;

	/**
	 * constructor
	 * @param type
	 * @param price
	 * @param id
	 */
	public PurchaseRequest(int type, float price, int id) {
		super();
		this.type = type;
		this.price = price;
		this.id = id;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

}
package com.example.demo.responsibility;

public abstract class Approver {
	
	/**
	 * Next processor
	 */
	Approver approver;
	/**
	 * Name
	 */
	String name;
	public Approver(String name) {
		super();
		this.name = name;
	}
	/**
	 * Next processor
	 * @param approver
	 */
	public void setApprover(Approver approver) {
		this.approver = approver;
	}

	/**
	 * The method of processing the approval request gets a request. The processing is completed by subclasses, so the method is made abstract
	 * @param purchaseRequest
	 */
	public abstract void processRequest(PurchaseRequest purchaseRequest);
	public String getName() {
		return name;
	}
	
}
package com.example.demo.responsibility;

public class CollegeApprover extends Approver{

	public CollegeApprover(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		// TODO Auto-generated method stub
		if (purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000) {
			System.out.println(" Request number id = " + purchaseRequest.getId() + " cover " + this.name + "Handle");
		} else {
			approver.processRequest(purchaseRequest);
		}
	}

}
package com.example.demo.responsibility;

public class DepartmentAPprover extends Approver{
	
	

	public DepartmentAPprover(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		// TODO Auto-generated method stub
		if (purchaseRequest.getPrice() <= 5000) {
			System.out.println(" Request number id = " + purchaseRequest.getId() + " cover " + this.name + "Handle");
		} else {
			approver.processRequest(purchaseRequest);
		}
	}
	
}
package com.example.demo.responsibility;

public class SchoolMasterApprover extends Approver {

	public SchoolMasterApprover(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		// TODO Auto-generated method stub
		if (purchaseRequest.getPrice() > 30000) {
			System.out.println(" Request number id = " + purchaseRequest.getId() + " cover " + this.name + "Handle");
		} else {
			approver.processRequest(purchaseRequest);
		}
	}

}
package com.example.demo.responsibility;

public class ViceSchoolMasterApprover extends Approver {

	public ViceSchoolMasterApprover(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		// TODO Auto-generated method stub
		if (purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000) {
			System.out.println(" Request number id = " + purchaseRequest.getId() + " cover " + this.name + "Handle");
		} else {
			approver.processRequest(purchaseRequest);
		}
	}

}
package com.example.demo.responsibility;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//Create a request
		PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 1);
		//Create relevant approvers
		DepartmentAPprover departmentApprover = new DepartmentAPprover("Director Zhang");
		CollegeApprover collegeApprover = new CollegeApprover("Dean Lee");
		ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("Vice Chancellor Wang"); 
		SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("President Tong");
		//The next approval level needs to be set up (the handler forms a circle:) 
		departmentApprover.setApprover(collegeApprover); 
		collegeApprover.setApprover(viceSchoolMasterApprover); 
		viceSchoolMasterApprover.setApprover(schoolMasterApprover); 
		schoolMasterApprover.setApprover(departmentApprover);
		//departmentApprover.processRequest(purchaseRequest);
		viceSchoolMasterApprover.processRequest(purchaseRequest);
	}

}

Source code of application of responsibility chain pattern in spring MVC framework







Summary of source code:
1) In the flow chart of spring MVC request, interceptor related method interceptor.preHandler and so on are executed.
2) When processing spring MVC requests, we use the responsibility chain pattern and the adapter pattern.
3) HandlerExecutionChain is responsible for the execution and processing of the request interceptor, but it does not process the request itself, only assigns the request to the registered processor on the chain for execution, which is the implementation of the responsibility chain, reduces the coupling between the responsibility chain itself and the processing logic, and regulates the processing flow of the chain.
4) HandlerExecutionChain maintains a collection of handlerinterceptors in the chain, from which corresponding interceptors can be registered.









Notes and details of responsibility chain model

1) Separate request and processing, realize decoupling, and improve the flexibility of the system.
2) Simplify chain objects so that they do not need to know the structure of the chain.
3) The performance will be affected, especially when the chain is relatively long, so it is necessary to control the maximum number of nodes in the chain. Generally, by setting a maximum number of nodes in the Handler, it is determined whether the threshold value has been exceeded in the setNext() method. If the threshold value is exceeded, the chain is not allowed to be established to avoid the unintentional destruction of system performance by the extra long chain.
4) The debugging is not convenient. Similar to recursion, the logic may be more complex when debugging.
5) Best application scenario: when multiple objects can handle the same request, such as multi-level request, leave / salary increase and other approval processes, Tomcat processing of inviting in Java Web, interceptor.



Posted by mwgi2005 on Sun, 05 Apr 2020 07:41:09 -0700