23 Design Patterns Chapter 19: Java Responsibility Chain Model
Definition: Allows multiple objects to have the opportunity to process the request, thus avoiding the coupling relationship between the sender and the receiver of the request. Connect these objects into a chain and pass the request along the chain until an object processes it.
Type: Behavioral Pattern
Class diagram:
Let’s first look at a piece of 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 as follows: the method has two parameters: the integer i and a request request. According to the value of i, who will handle the request, if i==1, it will be handled by Handler1, if i==2, it will be handled by Handler2, and so on.
In programming, this kind of business processing method is very common. All classes that process requests include if...else... conditional judgment statements connected into a chain of responsibility to process the request. I believe everyone often uses it. The advantages of this method are that it is very intuitive, simple and clear, and relatively easy to maintain, but this method also has several headaches:
Code bloated: In actual applications, the judgment conditions are usually not so simple to determine whether it is 1 or 2. It may require complex calculations, maybe querying the database, etc. This will have a lot of extra code. If there are many judgment conditions, then this if...else... statement is basically impossible to read.
High coupling degree: If we want to continue to add classes that process requests, we must continue to add else if judgment conditions; in addition, the order of this condition is also written to the dead. If we want to change the order, we can only modify this condition statement.
Since we have already understood the shortcomings, we need to find a way to solve them. The business logic of this scenario is very simple: if condition 1 is met, it will be processed by Handler1, and if it is not met, it will be passed down; if condition 2 is met, it will be processed by Handler2, and if it is not met, it will be passed down, and so on until the end of the condition. In fact, the improvement method is also very simple, which is to put the part of the judgment conditions into the processing class. This is the principle of the responsibility connection model.
The structure of the chain of responsibility model
The class diagram of the chain of responsibility pattern is very simple, it consists of an abstractly processed class and its set of implementation classes:
Abstract processing class: The abstract processing class mainly includes a member variable nextHandler pointing to the next processing class and a method handRequest that handles the request. The main idea of the handRequest method is that if the processing conditions are met, this processing class will be processed, otherwise it will be processed by nextHandler.
Specific processing class: Specific processing class mainly implements the specific processing logic and applicable conditions for processing.
After understanding the general idea of the responsibility chain model, it will be easier to understand when 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("----------"); } } 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("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ class ConcreteHandler2 extends Handler { protected Level getHandlerLevel() { return new Level(3); } public Response response(Request request) { System.out.println("--------------"); 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)); } }In the code, the Level class simulates the determination conditions; Request and Response correspond to requests and responses respectively; the abstract class Handler mainly judges the conditions, and a processing level is simulated here. Only the processing level of the processing class is higher than the level of the Request can be processed, otherwise it will be handed over to the next processor for processing.
Set the front and back execution relationship of the chain in the Client class, and hand over the request to the first processing class during execution. This is the responsibility chain pattern. The function it completes is the same as the if...else... statement in the previous article.
Pros and cons of the responsibility chain model
Compared with if…else…, the responsibility chain pattern has a lower coupling ability because it distributes the conditional judgments into various processing classes, and the priority processing order of these processing classes can be set at will. The responsibility chain model also has its disadvantages, which is the same as the if...else... statement, that is, before finding the correct processing class, all judgment conditions must be executed. When the responsibility chain is relatively long, the performance problem is more serious.
Applicable scenarios for the chain of responsibility model
Just like the beginning example, if you feel overwhelmed when using the if…else… statement to organize a chain of responsibility and the code looks bad, you can use the chain of responsibility mode to refactor it.
Summarize
The responsibility chain model is actually a flexible version of if...else... statement. It puts these judgment conditions into each processing class. The advantage of this is that it is more flexible, but it also brings risks. For example, when setting up the relationship between the processing class before and after the processing class, you must be very careful to judge the relationship between the conditional logic before and after the processing class, and be careful not to have circular references in the chain.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.