This is the 14th day of my participation in the August Text Challenge.More challenges in August

The chain of responsibility pattern creates a chain of recipient objects for the request. This pattern decouples the sender and receiver of the request. This type of design pattern is behavioral.

In this pattern, each receiver typically contains a reference to the other receiver. If an object cannot handle the request, it passes the same request to the next recipient, and so on.

introduce

describe parsing
intentions Avoid coupling the request sender with the receiver, make it possible for multiple objects to receive the request, connect the objects into a chain, and pass the request along the chain until an object handles it.
Mainly to solve The handler on the responsibility chain is responsible for processing the request, and the customer only needs to send the request to the responsibility chain without caring about the details of the request processing and the delivery of the request, so the responsibility chain decouples the sender of the request from the handler of the request.
When to use Filter many channels while processing messages.
How to solve The intercepting classes all implement a unified interface.
The key code It aggregates itself inside the Handler, determines whether it’s appropriate in the HandlerRequest, and if it’s not, passes it down, to whom the set goes in.
Examples of application 1. “Beat drums and pass flowers” in a Dream of Red Mansions. 2. Events bubble in JS. 3, JAVA WEB Apache Tomcat for Encoding processing, Struts2 interceptor, JSP servlet Filter.
advantages 1, reduce the coupling degree. It decouples the sender and receiver of the request. 2. Simplifying objects. The object does not need to know the structure of the chain. 3. Increase flexibility in assigning responsibilities to objects. Responsibilities can be dynamically added or removed by changing members in the chain or reordering them. 4. Adding new request handling classes is convenient.
disadvantages 1. There is no guarantee that the request will be received. 2, the system performance will be affected, and it is not convenient to debug the code, which may cause circular calls. 3. Runtime characteristics may not be easily observed, hindering debugging.
Usage scenarios 1. Multiple objects can handle the same request, which object handles the request is automatically determined by the runtime. 2. Submit a request to one of multiple objects without explicitly specifying the recipient. 3. Dynamically specify a set of objects to handle requests.
Matters needing attention You encounter many applications in the JAVA WEB.

implementation

The example sets up three loggers, each of which determines whether it needs processing and passes it to the next logger if it does not.

The abstract class AbstractLogger has a detailed logging level. And then there are three types of loggers, all of which extend AbstractLogger. Whether the level of each logger message is its own, and if so, prints it accordingly, otherwise it does not print and passes the message to the next logger.

\

Step 1- Create the abstract logger class

Create an abstract logger class.

// AbstractLogger.java public abstract class AbstractLogger { public static int INFO = 1; public static int DEBUG = 2; public static int ERROR = 3; protected int level; // Protected AbstractLogger nextLogger; public void setNextLogger(AbstractLogger nextLogger){ this.nextLogger = nextLogger; } public void logMessage(int level, String message){ if(this.level <= level){ write(message); } if(nextLogger ! =null){ nextLogger.logMessage(level, message); } } abstract protected void write(String message); }Copy the code

Step 2- Extend the instance class

Create an entity class that extends the logger class.

// ConsoleLogger.java public class ConsoleLogger extends AbstractLogger { public ConsoleLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("Standard Console::Logger: " + message); }}Copy the code
// ErrorLogger.java
public class ErrorLogger extends AbstractLogger {
 
   public ErrorLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("Error Console::Logger: " + message);
   }
}
Copy the code
// FileLogger.java public class FileLogger extends AbstractLogger { public FileLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("File::Logger: " + message); }}Copy the code

Step 3- Set the scene class

Create different types of loggers. Give them different error levels and set the next logger in each logger. The next logger in each logger represents part of the chain.

// ChainPatternDemo.java public class ChainPatternDemo { private static AbstractLogger getChainOfLoggers(){ AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR); AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG); AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO); errorLogger.setNextLogger(fileLogger); fileLogger.setNextLogger(consoleLogger); return errorLogger; } public static void main(String[] args) { AbstractLogger loggerChain = getChainOfLoggers(); loggerChain.logMessage(AbstractLogger.INFO, "This is an information."); loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information."); loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information."); }}Copy the code

Step 4- Output the results

Execute the program and output the result:

Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.
Copy the code