codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🎭

Design Patterns

20 / 100 topics
19Introduction to Behavioral Patterns20Chain of Responsibility Pattern21Command Pattern22Interpreter Pattern23Iterator Pattern24Mediator Pattern25Memento Pattern26Observer Pattern27State Pattern28Strategy Pattern29Template Method Pattern30Visitor Pattern33Practical Exercises for Behavioral Patterns
Tutorials/Design Patterns/Chain of Responsibility Pattern
🎭Design Patterns

Chain of Responsibility Pattern

Updated 2026-05-15
10 min read

Chain of Responsibility Pattern

Introduction

The Chain of Responsibility pattern is a behavioral design pattern that allows you to pass requests along a chain of potential handlers until one handles it. This pattern decouples the sender of a request from its receiver, giving more than one object a chance to handle the request.

In this tutorial, we'll explore how the Chain of Responsibility pattern works and provide practical examples in JavaScript.

Concept

The key idea behind the Chain of Responsibility pattern is to create a chain of handlers where each handler can either process the request or pass it along to the next handler in the chain. This pattern is particularly useful when you have multiple potential handlers for a single type of request, and you want to avoid hardcoding which handler should process the request.

Key Components

  1. Handler: An interface or abstract class that defines a method for handling requests.
  2. Concrete Handlers: Classes that implement the Handler interface and decide whether to handle the request or pass it along to the next handler in the chain.
  3. Client: The object that sends the request to the first handler in the chain.

Benefits

  • Decoupling: The sender of a request is decoupled from its receiver.
  • Flexibility: Handlers can be added, removed, or modified without affecting other handlers.
  • Scalability: New handlers can be easily added to handle new types of requests.

Examples

Let's dive into some practical examples to understand how the Chain of Responsibility pattern works.

Example 1: Logging System

Imagine you have a logging system where different log levels (e.g., DEBUG, INFO, ERROR) need to be handled by different handlers. We'll create a chain of responsibility for handling these log messages.

Step 1: Define the Handler Interface

class Logger {
  setNext(logger) {
    this.nextLogger = logger;
  }

  logMessage(level, message) {
    if (this.nextLogger) {
      this.nextLogger.logMessage(level, message);
    }
  }
}

#### Step 2: Implement Concrete Handlers

```javascript
class DebugLogger extends Logger {
  logMessage(level, message) {
    if (level === 'DEBUG') {
      console.log(`DEBUG: ${message}`);
    } else {
      super.logMessage(level, message);
    }
  }
}

class InfoLogger extends Logger {
  logMessage(level, message) {
    if (level === 'INFO') {
      console.log(`INFO: ${message}`);
    } else {
      super.logMessage(level, message);
    }
  }
}

class ErrorLogger extends Logger {
  logMessage(level, message) {
    if (level === 'ERROR') {
      console.error(`ERROR: ${message}`);
    } else {
      super.logMessage(level, message);
    }
  }
}

Step 3: Create the Chain and Handle Requests

const debugLogger = new DebugLogger();
const infoLogger = new InfoLogger();
const errorLogger = new ErrorLogger();

debugLogger.setNext(infoLogger);
infoLogger.setNext(errorLogger);

// Sending requests through the chain
debugLogger.logMessage('DEBUG', 'This is a debug message');
debugLogger.logMessage('INFO', 'This is an info message');
debugLogger.logMessage('ERROR', 'This is an error message');

Output

Output
DEBUG: This is a debug message
INFO: This is an info message
ERROR: This is an error message

Example 2: ATM Withdrawal Process

Consider an ATM machine that processes withdrawal requests. Different denominations can be handled by different handlers.

Step 1: Define the Handler Interface

class Dispenser {
  setNext(next) {
    this.nextDispenser = next;
  }

  dispense(amount) {
    if (this.nextDispenser) {
      this.nextDispenser.dispense(amount);
    }
  }
}

Step 2: Implement Concrete Handlers

class DenominationDispenser extends Dispenser {
  constructor(denomination) {
    super();
    this.denomination = denomination;
  }

  dispense(amount) {
    const count = Math.floor(amount / this.denomination);
    if (count > 0) {
      console.log(`Dispensing ${count} x ${this.denomination}`);
      amount -= count * this.denomination;
    }
    if (amount > 0 && this.nextDispenser) {
      this.nextDispenser.dispense(amount);
    }
  }
}

Step 3: Create the Chain and Handle Requests

const dispenser50 = new DenominationDispenser(50);
const dispenser20 = new DenominationDispenser(20);
const dispenser10 = new DenominationDispenser(10);

dispenser50.setNext(dispenser20);
dispenser20.setNext(dispenser10);

// Sending requests through the chain
dispenser50.dispense(70); // Dispensing 1 x 50, Dispensing 1 x 20

Output

Output
Dispensing 1 x 50
Dispensing 1 x 20

What's Next?

In the next section, we'll explore the Command Pattern, which is another behavioral design pattern that allows you to encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Stay tuned for more insightful tutorials on design patterns!


PreviousIntroduction to Behavioral PatternsNext Command Pattern

Recommended Gear

Introduction to Behavioral PatternsCommand Pattern