Chain of Responsibility Design Pattern

The Chain of Responsibility (CoR) design pattern is a behavioral pattern that is used to handle requests by passing them through a chain of objects until one of them handles the request. Each object in the chain has the capability to either handle the request or pass it on to the next object in the chain. This pattern is commonly used in scenarios where the handler of a request is not known beforehand.

In this article, we will explore the Chain of Responsibility design pattern in Java. We will first discuss the structure of the pattern, followed by an example of how it can be implemented in Java.

Structure of the Chain of Responsibility Pattern

The Chain of Responsibility pattern consists of three main components: the Handler interface, the ConcreteHandler class, and the Client class.

Handler: This is the interface that defines the methods for handling requests and passing them on to the next object in the chain. Each object that implements this interface has a reference to the next object in the chain.

ConcreteHandler: This is the class that implements the Handler interface. It handles requests that it is capable of handling, and passes on requests that it cannot handle to the next object in the chain.

Client: This is the class that initiates the request and passes it to the first object in the chain.

Example of the Chain of Responsibility Pattern

The Chain of Responsibility Pattern is a design pattern that allows a group of objects to handle a request, where each object in the group has the ability to either handle the request or pass it on to the next object in the chain.

In the context of banks, we can use the Chain of Responsibility Pattern to handle loan requests. Each bank in the chain can decide to approve or reject a loan request based on its own criteria, and if it rejects the request, it can pass it on to the next bank in the chain.

Here’s an example of the Chain of Responsibility Pattern in Java using banks:

public abstract class Bank {
private Bank nextBank;
public void setNextBank(Bank nextBank) {
    this.nextBank = nextBank;
}

public void processLoanRequest(double amount) {
    if (canApproveLoan(amount)) {
        System.out.println("Approved by " + getClass().getSimpleName());
    } else if (nextBank != null) {
        nextBank.processLoanRequest(amount);
    } else {
        System.out.println("Rejected by all banks");
    }
}

protected abstract boolean canApproveLoan(double amount);
}

public class SmallBank extends Bank {
@Override
protected boolean canApproveLoan(double amount) {
return amount <= 10000;
}
}

public class MediumBank extends Bank {
@Override
protected boolean canApproveLoan(double amount) {
return amount <= 50000;
}
}

public class LargeBank extends Bank {
@Override
protected boolean canApproveLoan(double amount) {
return amount <= 100000;
}
}


In this example, Bank is an abstract class that represents a bank in the chain. It has a setNextBank method to set the next bank in the chain, and a processLoanRequest method to process a loan request. The canApproveLoan method is an abstract method that each concrete bank class must implement to specify its criteria for approving a loan.

SmallBank, MediumBank, and LargeBank are concrete classes that extend Bank and implement their own criteria for approving a loan. SmallBank can approve loans up to $10,000, MediumBank can approve loans up to $50,000, and LargeBank can approve loans up to $100,000.

To use the Chain of Responsibility Pattern, we create an instance of each bank and set the next bank in the chain:


 public class Main {
    public static void main(String[] args) {
    Bank smallBank = new SmallBank();
    Bank mediumBank = new MediumBank();
    Bank largeBank = new LargeBank();
    smallBank.setNextBank(mediumBank);
    mediumBank.setNextBank(largeBank);

    smallBank.processLoanRequest(5000); // Approved by SmallBank
    smallBank.processLoanRequest(25000); // Approved by MediumBank
    smallBank.processLoanRequest(75000); // Approved by LargeBank
    smallBank.processLoanRequest(150000); // Rejected by all banks
}
}


In this example, we create instances of SmallBank, MediumBank, and LargeBank, and set the next bank in the chain using the setNextBank method. We then call the processLoanRequest method on smallBank with various loan amounts, and the chain of banks handles the requests according to their criteria.

Practical use of Chain of Responsibility Design Pattern

The Chain of Responsibility Design Pattern is commonly used in real-world scenarios where a request needs to be handled by multiple objects, and the responsibility for handling the request needs to be passed on dynamically between these objects until it’s handled.

Here are some examples of real-life use cases of the Chain of Responsibility Design Pattern:

Logging and Debugging:
In a logging and debugging system, each logging component can be represented as an object in the chain. Each logging component can decide whether to handle a log message based on the log level and the component’s capabilities. If it can’t handle the log message, it passes it on to the next component in the chain.

Online Purchasing System:
In an online purchasing system, a purchase request can be represented as an object in the chain. Each object in the chain can represent a different step in the purchasing process, such as checking inventory, processing payment, and shipping. If an object can’t handle the purchase request, it passes it on to the next object in the chain until the request is handled.

Exception Handling:
In an application, exceptions can be handled using the Chain of Responsibility Design Pattern. Each exception handler can be represented as an object in the chain. If an exception occurs, it’s passed on to the first handler in the chain. If the handler can handle the exception, it does so, and the chain stops. If it can’t handle the exception, it passes it on to the next handler in the chain.

Employee Approval Hierarchy:
In a large organization, employee approvals can be represented as an object in the chain. Each employee can be assigned a level of authority, and the approval request can be passed on to the next employee in the chain until it’s approved or rejected.

Overall, the Chain of Responsibility Design Pattern is a useful pattern for managing the responsibility of multiple objects in a dynamic and flexible way.

1 Comment

Comments are closed