The Chain of Responsibility pattern is a behavioral design pattern that allows objects to pass the request along a chain of handlers. When a request is received a handler decides on either to process it or pass it along the chain. the object does not know which handler will process the request.

Motivation
The pattern is used to reduce the tight coupling between the request object and the handlers that process it. Instead of sending a request directly to a specific object and using conditional statements to determine how the request will be processed, the client sends it to the first handler in the chain, thus decoupling the sender and receiver objects.

Implementation
Considering that you are developing an application that determines the customer support staff that will handle a customer's issue for a company. All issues are first checked by Level1CustomerSupport if the issue is "basic", he attends to the customer else he sends the customer to Level2CustomerSupport. The Level2CustomerSupport then checks the customer's issue if it's "intermediate" so he can attend to it if "complex" he sends it to Level3CustomerSupport.
Level3CustomerSupport resolves complex issues only.

Instead of having a single class with multiple if and else statements checking on how difficult the issue is, the Chain of Responsibility pattern helps to decouple the issue from the handler who handles such issues and makes it pass through the chain of handlers who decide whether they can resolve the issues.

The CustomerSupport defines the abstract class for creating a customer support object. the level1, level2, and level3 support will extend from this class.
The setNextLevel function helps handle the hierarchy in the customer support department by setting the level above the current support level.

The resolveIssue function is the one that checks if the issue can be resolved by the current support level or if it will be delegated to the next support level.

public abstract class CustomerSupport { protected CustomerSupport nextLevel; public void setNextLevel(CustomerSupport nextLevel) { this.nextLevel = nextLevel; } public abstract void resolveIssue(String issue); } 
public class Level1CustomerSupport extends CustomerSupport{ @Override public void resolveIssue(String issue) { if ("basic".equals(issue)) { System.out.println("Level 1 CSR resolves the basic issue."); } else if (nextLevel != null) { nextLevel.resolveIssue(issue); } } } 
public class Level2CustomerSupport extends CustomerSupport{ @Override public void resolveIssue(String issue) { if ("intermediate".equals(issue)) { System.out.println("Level 2 CSR resolves the intermediate issue."); } else if (nextLevel != null) { nextLevel.resolveIssue(issue); } } } 
public class Level3CustomerSupport extends CustomerSupport{ @Override public void resolveIssue(String issue) { if ("complex".equals(issue)) { System.out.println("Level 3 CSR resolves the complex issue."); } else { System.out.println("This issue cannot be resolved."); } } } 

Level1CustomerSupport sets the next level to Level2CustomerSupport and Level2CustomerSupport sets the next level to Level3CustomerSupport which defines the hierarchy. As outlined previously, Level1CustomerSupport resolves all the issues and filters to see what can be resolved.

 CustomerSupport customerSupport1 = new Level1CustomerSupport(); CustomerSupport customerSupport2 = new Level2CustomerSupport(); CustomerSupport customerSupport3 = new Level3CustomerSupport(); customerSupport1.setNextLevel(customerSupport2); customerSupport2.setNextLevel(customerSupport3); customerSupport1.resolveIssue("basic"); customerSupport1.resolveIssue("intermediate"); customerSupport1.resolveIssue("complex"); 

The result of the application shows that Level1CustomerSupport resolves the basic issues, Level2CustomerSupport, and Level3CustomerSupport resolves intermediate and complex respectively.

Level 1 CSR resolves the basic issue. Level 2 CSR resolves the intermediate issue. Level 3 CSR resolves the complex issue. 

Advantages

  1. It reduces the coupling between the request object and the receiver objects (handlers).
  2. It allows adding or removing responsibilities dynamically by changing the members or order of the chain.

Disadvantages

  1. There's a possibility that a request is not processed; it might fall off the end of the chain if no object handles it.
  2. It might make the system a bit more complex to understand and maintain due to the indirect communication between objects.

Usecase

Conclusion
The Chain of Responsibility Pattern is an excellent way to decouple sender and receiver objects, allowing multiple objects to handle the request independently. Care should be taken to manage the chain correctly to ensure that the request is handled appropriately and make sure that the code is easy to comprehend.