Chain of Responsibility Design Pattern


Responsibility Chain Mode

As the name implies, the Chain of Responsibility Pattern creates a chain of recipient objects for the request. This mode gives the type of request and decouples the sender and receiver of the request. This type of design pattern is a behavioral model.

In this mode, usually each recipient 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.

Introduction

Intent: Avoid requesting that the sender and receiver are coupled together, making it possible for multiple objects to receive requests, concatenating these objects into a chain, and passing requests along this chain. Until an object handles it.

Main solution: The processor on the responsibility chain is responsible for processing the request. The client only needs to send the request to the chain of responsibility. It does not need to care about the processing details of the request and the delivery of the request, so the chain of responsibility Decoupled the sender of the request from the handler of the request.

When to use: Filter a lot when processing messages.

How to solve: The intercepted classes all implement a unified interface.

Key code: The Handler aggregates itself, determines whether it is appropriate in the HandlerRequest, and if it does not reach the condition, it passes down, and before it is passed, the set is entered.

Application example: 1. "Drums and flowers" in the Dream of Red Mansions. 2. The event in JS bubbling. 3, JAVA WEB Apache Tomcat processing of Encoding, Struts2 interceptor, jsp servlet Filter.

Advantages: 1. Reduce the coupling degree. It decouples the sender and receiver of the request. 2. Simplified the object. This makes it unnecessary for the object to know the structure of the chain. 3. Enhance the flexibility of assigning responsibilities to objects. Allows you to dynamically add or remove responsibilities by changing the members of the chain or by arranging them. 4. It is convenient to add new request processing classes.

Disadvantages: 1. There is no guarantee that the request will be received. 2, system performance will be affected, and it is not convenient when debugging the code, it may cause a loop call. 3. It may not be easy to observe the characteristics of the runtime, which hinders the debugging.

Usage scenarios: 1. There are multiple objects that can process the same request, and 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. A set of object processing requests can be dynamically specified.

Note: There are many applications encountered in JAVA WEB.

Implementation

We created the abstract class AbstractLogger with a detailed logging level. Then we created three types of loggers, all of which extend AbstractLogger. Whether the level of each logger message belongs to its own level, and if so, prints it accordingly, otherwise it will not print and pass the message to the next logger.

chain_pattern_uml_diagram.jpg

Step 1

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; //The next element in the chain of responsibility 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 writeStep h2

Create an entity class that extends the logger class.

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); } }

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); } }

Step 3

Create different types of loggers. Give them different levels of error and set the next logger in each logger. The next logger in each logger represents a 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 an debug level information."); loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information."); } }





javacodegeeks is optimized for learning.© javacodegeeks .
All Right Reserved and you agree to have read and accepted our term and condition