This is the 8th day of my participation in the August Text Challenge.More challenges in August
In his book Java and Patterns, Dr. Yan Hong describes the Chain of Responsibility mode as follows:
Chain of responsibility is an object behavior pattern. In the chain of responsibility pattern, many objects are connected in a chain by each object’s reference to its next parent. Requests pass along the chain until one of the objects on the chain decides to process the request. The client making the request does not know which object on the chain ultimately handles the request, allowing the system to dynamically reorganize and assign responsibilities without affecting the client.
Generally speaking, the chain of responsibility mode means that a initiated request has multiple different processors, and different processors have different abilities and permissions. After the process control of the system, the request is finally processed by the processor with the corresponding permissions. That is, multiple objects can receive the same request, but which object to process is determined dynamically at run time.
For example, in the company initiated leave process, you fill in leave for 10 days, the process launched, the group leader a look “I damn, 10 days of vacation, I can not approve”, the group leader forward the message to the director, the director can not deal with, and then the director forward to the department manager, department manager approval end.
In the example above, we do not know who finally processed our request, only to get the final result, the fake order was approved. Similarly, in the chain of responsibility mode, the client does not know who finally processes the process, and the client only needs to send the request through the outbound interface.
UML diagrams
The chain of responsibility model involves the following roles:
- The abstract Handler role (Handler) : Abstract defines the interface to handle requests, which can be performed by an abstract class or interface.
- ConcreteHandler: The actual implementer of a request. Upon receiving a request, the ConcreteHandler can choose to either process it or forward it to the next handler.
Case scenario
Let’s use the above pseudo-single flow processing as an example for parsing.
Abstract event processing interface firstly abstracts the leave processing process that needs to be processed according to the requirements.
/** * defines the abstract processing class *@author Iflytek_dsw
*
*/
abstract class IHandler{
protected IHandler handler;
public abstract boolean handleRequest(int leaveDay);
}
Copy the code
The abstract interface contains a reference to a Handler, which is at the heart of the whole chain of concerns because it allows each Handler to relate to each other. Define specific event handlers. Our leave process will be first submitted to our team leader, and then to a level such as supervisor and department manager. If we ask for leave for one day, it will be ok for the team leader to directly approve it.
/** * Team leader *@author Iflytek_dsw
*
*/
class ChargeHand extends IHandler{
@Override
public boolean handleRequest(int leaveDay) {
if(leaveDay <= 1){
System.out.println("Team leader handles leave and approves.");
return true;
}else{
returnhandler.handleRequest(leaveDay); }}}/** **@author Iflytek_dsw
*
*/
class ChargeLeader extends IHandler{
@Override
public boolean handleRequest(int leaveDay) {
if(leaveDay <= 5){
System.out.println("In charge of handling leave, approved.");
return true;
}else{
returnhandler.handleRequest(leaveDay); }}}/** * Department manager approval *@author Iflytek_dsw
*
*/
class DepartmentLeader extends IHandler{
@Override
public boolean handleRequest(int leaveDay) {
if(leaveDay <= 10){
System.out.println("Department manager handles leave and approves it.");
return true;
}else{
System.out.println("Human resources direct record, approved.");
return true; }}}Copy the code
The abstract interfaces and handlers of the chain relationships are defined, but they are not yet chained, and the client does not have to build the chain for this purpose, nor does he have the right to do so. So we need to build this chain.
/** ** *@author Iflytek_dsw
*
*/
public class LeaveProcess {
private static LeaveProcess instance;
private IHandler chargeHandler,leaderHandler,departmentHandler;
private LeaveProcess(a){
/** * create the corresponding handler for this, and build the chain */
chargeHandler = new ChargeHand();
leaderHandler = new ChargeLeader();
departmentHandler = new DepartmentLeader();
chargeHandler.handler = leaderHandler;
leaderHandler.handler = departmentHandler;
};
public static LeaveProcess getInstance(a){
if(instance == null) {synchronized(LeaveProcess.class){
if(instance == null){
instance = newLeaveProcess(); }}}return instance;
}
/** * Submit a leave request to the immediate group leader *@paramLeaveDay Number of days off *@return* /
public boolean sendLeaveProcess(int leaveDay){
returnchargeHandler.handleRequest(leaveDay); }}Copy the code
In the LeaveProcess class, references to all handlers are held, and a chain is established between them so that the process is “automatically” distributed.
The client
public class Client {
/ * * *@param args
*/
public static void main(String[] args) {
if(LeaveProcess.getInstance().sendLeaveProcess(8)){
System.out.println("8 days leave approved.");
}else{
System.out.println("Not approved"); }}}Copy the code
This encapsulates the process, and for the client, it doesn’t know or need to know who handles it, just the result of the execution.
The advantages and disadvantages
Advantages:
- Reduce coupling. It decouples the sender and receiver of the request.
- Simplifies the object. The object does not need to know the structure of the chain.
- Enhanced flexibility in assigning responsibilities to objects. Responsibilities can be dynamically added or removed by changing members in the chain or reordering them.
- It is convenient to add new request handling classes.
Disadvantages:
- There is no guarantee that the request will be received.
- System performance will suffer, and it will be inconvenient to debug the code, which may cause circular calls.
- Runtime characteristics may not be easily observed, hindering debugging.
Usage Scenarios:
- Multiple objects can handle the same request, and which object handles the request is automatically determined by the runtime.
- Submit a request to one of multiple objects without explicitly specifying the recipient.
- You can dynamically specify a set of objects to handle requests.