NailYourInterview
Behavioural Design Patterns

Chain of Responsibility Design Pattern in Java Example

Explore the Chain of Responsibility Design Pattern in Java with real-world cases like interviews, document approvals, and logging chains. Easy and practical guide.

Chain Of Responsibility Design Pattern

Video thumbnail

The Chain of Responsibility (CoR) pattern is a behavioral design pattern that lets you pass a request along a chain of handlers. Each handler decides either to process the request or to pass it on to the next handler in the chain.

Real-Life Examples

Interview Process

Let’s say you've applied for a job at Amazon and cleared the initial resume shortlisting. Now, you go through a series of interviews:

  • Technical Interview

  • Bar Raiser Interview

  • HR Interview

Your hiring depends on clearing all three rounds. A basic way to represent this in code would look like:

Main.java
public class Main {
    public static void main(String[] args) {
        String candidate = "Alice";
 
        TechnicalInterview technicalInterview = new TechnicalInterview();
        if(!technicalInterview.hire(candidate)) return;
 
        BarRaiserInterview barraiserInterview = new BarRaiserInterview();
        if(!barraiserInterview.hire(candidate)) return;
 
        HRInterview hrInterview = new HRInterview();
        if(!hrInterview.hire(candidate)) return;
 
        System.out.println(candidate + " passed all interviews!");
    }
}

Problem with this approach

  1. Code duplication: You’ll need to write this same logic every time you want to use this process.

  2. Hard to maintain: If a new round is added, removed, or updated, you’ll need to touch this code again. This violates the Open/Closed Principle.

  3. Interruption risk: Someone might accidentally insert extra logic between rounds (e.g., analytics), which could break the intended flow.

Using Chain of Responsibility

What if each interview round only took care of its own step and forwarded the result to the next round automatically? That’s exactly what Chain of Responsibility does.

Chain Of Responsibility Design Pattern Example - Interview Process
Chain Of Responsibility Design Pattern Example - Interview Process

This gives us several benefits:

  • No code duplication

  • Easy to add/remove rounds

  • Central control stays intact

  • Follows the Open/Closed Principle (we can add new interview rounds without touching the main logic)

Documentation Review

Say you've created a documentation draft and want it reviewed. Based on the authority level of the doc, the following people can review it:

  • Team Lead (level 1)

  • Manager (level 2)

  • Director (level 3)

If the document’s authority level is 1, the team lead can approve. If it’s 2, only the manager or director can approve. So, the document is passed up the chain until it finds the right handler.

Chain Of Responsibility Design Pattern Example - Interview Process
Chain Of Responsibility Design Pattern Example - Interview Process

Notice that you don't care who approves it - as long as someone qualified does.

This is where COR fits beautifully. The request (document) flows through a chain of handlers (reviewers), and the right one acts on it.

Logging

You want to log events to multiple outputs: console, file, and email. You might think of doing this with a loop:

for (Logger logger : allLoggers) {
    logger.log(msg);
}
Chain Of Responsibility Design Pattern Example - Logging
Chain Of Responsibility Design Pattern Example - Logging

But with COR, you chain the loggers, and each one decides whether to process the message or not. Some may pass it along, others may stop it.

Types of COR

Let’s look at some common variations:

  1. Only One Handler Will Process: Only the first eligible handler processes the request. Others don't get a chance. Example: Documentation review. Only one person should approve it.

  2. Break Chain Based on a Condition: Each handler processes the request and decides whether to continue. Example: Interview process. If one round fails, no need to continue.

  3. All Handlers Will Process: Every handler in the chain processes the request. Example: Logging. All loggers (console, file, email) log the message.

COR Type 3 vs Decorator

  • In Decorator, the object is modified/enhanced as it moves through the chain (e.g., Plain Pizza → Cheese Pizza → Sauce Cheese Pizza).
  • In COR, the same originial object/request is passed through handlers.

When Should You Use Chain of Responsibility?

Use COR when:

  1. You can think about chain of processing steps, each responsible for a small part of the logic.

  2. You want to decouple the sender of a request from its receiver. In simpler words, client is unsure about the receiver(s).

UML Diagram

UML for Chain Of Responsibility Design Pattern
UML for Chain Of Responsibility Design Pattern
  • Handler (abstract class/interface): Contains a reference to the next handler and defines a method like handle(request) or hire(candidate).

  • Concrete Handlers: Implement the actual logic. They process the request or pass it to the next handler if they can’t handle it.

Key Benefits of the Chain of Responsibility Pattern

On this page