The Chain of Responsibility (COR) design pattern is used when more than one object handles a request and performs their corresponding responsibilities to complete the whole task.

The pattern can be used to achieve loose coupling in software design, where the request can be passed through a chain of objects or request handler for processing. Based on some criteria in each handler object, it will handle the request or pass it to the next handler. Following is a representation of the COR pattern:

The COR pattern can be implemented in two ways.

1. One Request Handler Will Serve the Input Request

The request initiator is not aware of the exact handler that will serve its request. Every handler in the chain will have the responsibility to decide if they can serve the request. If any handler decides to forward the request, it should be capable of choosing the next handler and forwarding it. There is a possible scenario in which none of the handlers may serve the request.

This type of COR pattern implementation is present in Java’s exception handling mechanism. We can have multiple catch blocks in a try-catch block code. Here, every catch block is kind of a handler to handle that particular exception.

When an exception occurs in the try block, it sends the exception to the first catch block to process. If the catch block is not able to handle it, it forwards the exception to the next handler in the chain, i.e. the next catch block. If even the last catch block is not able to handle it, then the exception is thrown outside of the chain to the calling program.

2. Multiple Request Handlers Will Serve the Input Request

There is another type of COR pattern implementation in which more than one handler participates in the processing to complete the whole task. In this implementation, each handler performs its part of the task (if required based on some condition) and forwards the request to the next handler. The whole task is completed once the request travels through the complete chain.

Spring’s HandlerInterceptorAdapter is an example of this type of COR pattern. The HandlerInterceptorAdapter defines three methods: preHandle(), postHandle(), and afterCompletion(). Here, the preHandle() follows the COR pattern if we have multiple interceptors for intercepting a request. Then, the request flows through all the preHandle() methods sequentially, and each preHandle() can perform some task and modify the request before it reaches to the controller. Here’s what a simple preHandle() implementation will look like:

This method is called before handling a request. If it returns true, the Spring framework sends the request further to the next handler method (to the next interceptor’s preHandle). If the method returns false, Spring assumes that request has been handled, and no further processing is required. By this boolean flag, each handler of the chain chooses the next handler. Now, let's consider a simple implementation of COR pattern.

We have a request that needs to collect data from different external third-party data storages like a database, file storage, and cloud environments. We will develop a chain of such data collectors that are responsible for collecting data from different sources. First, we will define the type of RequestHandler.

This is an interface defining the basic blueprint of all the concrete RequestHandlers.

Now, we will define the three concrete request handlers that are responsible for collecting data from each of the sources (database, file, and cloud). In addition, each handler has a pointer to the next handler object so that control can be passed to the next handler when the current handler finishes.

Now, let's test the code. Here, we are creating an object of each handler type, then creating a chain of handlers, and finally calling the process method of the first handler object in the chain. The first handler will call the next handler when it is finished, and this step will be continued until the chain is finished.