Responsibility chain model
The responsibility chain pattern is a behavior design pattern that allows you to send requests along the handler chain. After receiving the request, each handler can process the request or pass it to the next handler in the chain.
In the responsibility chain pattern, each recipient usually contains a reference to another recipient. If an object cannot process the request, it passes the same request to the next recipient, and so on.
The responsibility chain decouples the sender of the request from the handler of the request.
Summary: pass the request from one object in the chain to the next until the request is responded to. In this way, the coupling between objects is removed.
There are two situations in the responsibility chain mode.
- Pure responsibility chain mode: a request must be received by a handler object, and a specific handler can only adopt one of the following two behaviors for processing a request: self processing (assuming responsibility); Shift the responsibility to the next family.
- Impure responsibility chain mode: it allows a specific handler object to transfer the remaining responsibility to the next home after assuming part of the responsibility of the request, and a request can not be received by any receiving end object.
Pattern structure
- Handler: an abstract handler, which defines an interface for processing requests and means another handler
- ConcreteHandler A and B are specific handlers. They handle the requests they are responsible for and can access their successors (i.e. the next handler). If they can handle the current request, they will handle it. Otherwise, they will hand over the request to a successor to handle it, so as to form a responsibility chain
- Request: it means many attributes and represents a request.
Class diagram
Advantages and disadvantages
advantage:
- 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 the clear information of each other.
- Single responsibility principle. You can decouple the classes that initiate and execute operations.
- Opening and closing principle. You can add processors in the program without changing the existing code, which enhances the scalability of the system.
- 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.
- 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.
Disadvantages:
- Some requests may not be processed.
- If the responsibility chain is long, the request processing may involve multiple processing objects, and the system performance will be affected to some extent.
- The rationality of the establishment of responsibility chain depends on the client, which increases the complexity of the client.
Responsibility chain pattern in spring MVC
The responsibility chain pattern is used in the spring MVC handlerexecutionchain class.
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
-
- The HandlerExecutionChain maintains a collection of handlerinterceptors to which corresponding interceptors can be registered
- The HandlerExecutionChain maintains a collection of handlerinterceptors to which corresponding interceptors can be registered
Application scenario
- Multiple objects can handle a request, but the specific object that handles the request is automatically determined at run time.
- When multiple processors must be executed sequentially, the responsibility chain pattern can be used.
- If the required processors and their order must be changed at run time, the responsibility chain mode can be used.
- You need to dynamically specify a set of objects to handle requests or add new processors.
- You need to submit a request to one of multiple processors without explicitly specifying the request processor.
Sample code
Procurement approval process of school OA system
public abstract class ApprovalHandle { protected ApprovalHandle approvalHandle; protected String approvalName; public ApprovalHandle(String approvalName){ this.approvalName = approvalName; } protected void setApproval(ApprovalHandle approvalHandle){ this.approvalHandle = approvalHandle; } protected abstract void handleRequest(PurchaseRequest request); } public class ChainOfResponsibilityPattern { public static void main(String[] args) { PurchaseRequest request = new PurchaseRequest(1,8000); ApprovalHandle classApproval = new ClassApproval("headmaster"); ApprovalHandle departmentApproval = new DepartmentApproval("Dean of Department"); ApprovalHandle deanApproval = new DeanApproval("Director of the hospital"); ApprovalHandle masterApproval = new MasterApproval("School director"); classApproval.setApproval(departmentApproval); departmentApproval.setApproval(deanApproval); deanApproval.setApproval(masterApproval); masterApproval.setApproval(classApproval); classApproval.handleRequest(request); } } public class ClassApproval extends ApprovalHandle { public ClassApproval(String approvalName) { super(approvalName); } @Override protected void handleRequest(PurchaseRequest request) { if (request.getPrice() <= 5000){ System.out.println("Number is"+request.getId()+"Request from"+approvalName + "To handle"); } else if (approvalHandle != null){ approvalHandle.handleRequest(request); } else System.out.println("No one wants to deal with it"); } } public class DeanApproval extends ApprovalHandle{ public DeanApproval(String approvalName) { super(approvalName); } @Override protected void handleRequest(PurchaseRequest request) { if (request.getPrice() > 10000 && request.getPrice() <= 30000){ System.out.println("Number is"+request.getId()+"Request from"+approvalName + "To handle"); } else if (approvalHandle != null){ approvalHandle.handleRequest(request); } else System.out.println("No one wants to deal with it"); } } public class DepartmentApproval extends ApprovalHandle{ public DepartmentApproval(String approvalName) { super(approvalName); } @Override protected void handleRequest(PurchaseRequest request) { if (request.getPrice() > 5000 && request.getPrice() <= 10000){ System.out.println("Number is"+request.getId()+"Request from"+approvalName + "To handle"); } else if (approvalHandle != null){ approvalHandle.handleRequest(request); } else System.out.println("No one wants to deal with it"); } } public class MasterApproval extends ApprovalHandle{ public MasterApproval(String approvalName) { super(approvalName); } @Override protected void handleRequest(PurchaseRequest request) { if (request.getPrice() > 30000 ){ System.out.println("Number is"+request.getId()+"Request from"+approvalName + "To handle"); } else if (approvalHandle != null){ approvalHandle.handleRequest(request); } else System.out.println("No one wants to deal with it"); } } public class PurchaseRequest { private int price; private int id; public PurchaseRequest(int id ,int price) { this.id = id; this.price = price; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public int getId() { return id; } public void setId(int id) { this.id = id; } }