23 Design Patterns (19) - Responsibility Chain Patterns

Definition: Enables multiple objects to process requests, thereby avoiding coupling between the sender and receiver of the request.Join these objects into a chain and pass the request along the chain until an object handles it.

 

Type: Behavior class pattern

 

Class Diagram:

Let's start with a code:

public void test(int i, Request request){  
   if(i==1){  
       Handler1.response(request);  
   }else if(i == 2){  
       Handler2.response(request);  
   }else if(i == 3){  
       Handler3.response(request);  
   }else if(i == 4){  
       Handler4.response(request);  
   }else{  
       Handler5.response(request);  
   }  
}

 

The business logic of the code is that there are two parameters to the method: an integer I and a request request, which determine who will process the request based on the value of i, a handler 1 if i==1, a handler 2 if i==2, and so on.

 

In programming, this method of handling business is very common, and all classes that handle requests are if...else...Conditional judgment statements form a chain of responsibilities to handle requests, which we believe are often used.The advantages of this method are intuitive, simple and easy to maintain, but there are several more headaches with this method:

 

Bloated code: In practical applications, the criteria are usually not so simple as to determine whether 1 or 2 is, complex calculations, queries to databases, etc. There will be a lot of extra code. If there are more criteria, then this if...else...Statements are basically impossible to read.

 

High coupling: If we want to continue adding classes to process requests, then we need to continue adding else criteria; in addition, the order of criteria determination is also written to death, and if we want to change the order, we can only modify this conditional statement.

 

Now that we know the shortcomings, we need to find ways to solve them.The business logic for this scenario is simple: if condition 1 is met, it is handled by Handler 1, and if it is not satisfied, it is handled by Handler 2, and if it is not, it continues to pass down, and so on, until the condition ends.In fact, the improvement method is also very simple, that is, put part of the criteria to the processing class, which is the principle of the liability company mode.

 

The structure of the responsibility chain model

The class diagram of the responsibility chain pattern is very simple, consisting of an abstract processing class and a set of its implementation classes:

Abstract Processing Class: The abstract processing class mainly contains a member variable nextHandler pointing to the next processing class and a method handRequest for processing requests. The main idea of the handRequest method is that if the processing conditions are met, there will be this processing class for processing, otherwise, it will be handled by nextHandler.

Specific processing class: The specific processing class mainly implements the specific processing logic and the applicable conditions of the processing.

 

Once you understand the general idea of the responsibility chain model, you can better understand it by looking at the code:

class Level {  
       private int level = 0;  
       public Level(int level){  
           this.level = level;  
       };  
         
       public boolean above(Level level){  
           if(this.level >= level.level){  
               return true;  
           }  
           return false;  
       }  
   }  
     
   class Request {  
       Level level;  
       public Request(Level level){  
           this.level = level;  
       }  
         
       public Level getLevel(){  
           return level;  
       }  
   }  
     
   class Response {  
     
   }  
     
   abstract class Handler {  
       private Handler nextHandler;      
       public final Response handleRequest(Request request){  
           Response response = null;  
             
           if(this.getHandlerLevel().above(request.getLevel())){  
               response = this.response(request);  
           }else{  
               if(this.nextHandler != null){  
                   this.nextHandler.handleRequest(request);  
               }else{  
                   System.out.println("-----No suitable processor-----");  
               }  
           }  
           return response;  
       }  
       public void setNextHandler(Handler handler){  
           this.nextHandler = handler;  
       }  
       protected abstract Level getHandlerLevel();  
       public abstract Response response(Request request);  
   }  
     
   class ConcreteHandler1 extends Handler {  
       protected Level getHandlerLevel() {  
           return new Level(1);  
       }  
       public Response response(Request request) {  
           System.out.println("-----Requests are processed by processor 1-----");  
           return null;  
       }  
   }  
     
   class ConcreteHandler2 extends Handler {  
       protected Level getHandlerLevel() {  
           return new Level(3);  
       }  
       public Response response(Request request) {  
           System.out.println("-----Requests are processed by processor 2-----");  
           return null;  
       }  
   }  
     
   class ConcreteHandler3 extends Handler {  
       protected Level getHandlerLevel() {  
           return new Level(5);  
       }  
       public Response response(Request request) {  
           System.out.println("-----Requests are processed by processor 3-----");  
           return null;  
       }  
   }  
     
   public class Client {  
       public static void main(String[] args){  
           Handler handler1 = new ConcreteHandler1();  
           Handler handler2 = new ConcreteHandler2();  
           Handler handler3 = new ConcreteHandler3();  
     
           handler1.setNextHandler(handler2);  
           handler2.setNextHandler(handler3);  
             
           Response response = handler1.handleRequest(new Request(new Level(4)));  
       }  
   }

 

The Level class in the code is a simulated decision condition; Request, Response corresponds to request and response respectively; the abstract class Handler mainly makes conditional judgment, where a processing level is simulated. Only if the processing level of the processing class is higher than that of Request, can it be handled by the next handler, otherwise it is handled by the next one.

 

The chain execution relationship is set up in the Client class, and the request is handed over to the first processing class when it is executed. This is the responsibility chain mode, which completes the function with if in the preceding article.else...Statement is the same.

 

Advantages and disadvantages of the responsibility chain model

Responsibility Chain Model and if...else...Its coupling is lower than that because it distributes conditional decisions among processing classes, and the preference of those processing classes can be set at will.The liability chain model also has drawbacks, which is in contrast to if...else...The disadvantage of statements is that all the criteria are executed once before finding the correct processing class, and performance problems are more serious when the responsibility chain is longer.

 

Scenarios for applying the responsibility chain model

As in the first example, if you use if...else...Statements can be overwhelming when organizing a chain of responsibility, and code can be refactored using a chain of responsibility pattern when it looks bad.

 

summary

The responsibility chain model is a flexible version of if...else...Statement, it is to place the statements of these criteria into each processing class. This has the advantage of flexibility, but it also brings risks. For example, when setting up the relationship between before and after a class, you must be very careful to make judgments about the conditions of the logic before and after the class, and be careful not to have circular references in the chain.

43 original articles published. 1. Visits 1013
Private letter follow

Tags: Programming

Posted on Mon, 09 Mar 2020 19:37:01 -0700 by beachdaze