Skip to main content

Chain of Responsibility Pattern in JavaScript (Live Playground)

The Chain of Responsibility pattern is a behavioral design pattern that enables you to pass requests along a chain of handlers. Each handler decides whether to process the request or pass it along to the next handler in the chain. In this tutorial, we'll explore the Chain of Responsibility pattern in JavaScript, including its use cases, implementation, and benefits.

Why Use the Chain of Responsibility Pattern?

The Chain of Responsibility pattern is useful when you want to:

  1. Decouple the sender of a request from its receiver by allowing multiple objects to handle the request.
  2. Enable dynamic handling of requests, with each handler deciding whether to process the request or pass it along.
  3. Improve code maintainability and scalability by promoting loose coupling and separation of concerns.

Implementing the Chain of Responsibility Pattern in JavaScript

Here's an example of how to implement the Chain of Responsibility pattern using JavaScript classes:

TypeScript
// Handler interface
class Handler {
setNext(handler) {
this.nextHandler = handler;
return handler;
}

handle(request) {
if (this.nextHandler) {
return this.nextHandler.handle(request);
}
return null;
}
}

// Concrete handlers
class ConcreteHandler1 extends Handler {
handle(request) {
if (request === 'Request1') {
return `ConcreteHandler1 handling ${request}`;
}
return super.handle(request);
}
}

class ConcreteHandler2 extends Handler {
handle(request) {
if (request === 'Request2') {
return `ConcreteHandler2 handling ${request}`;
}
return super.handle(request);
}
}

// Client code
const handler1 = new ConcreteHandler1();
const handler2 = new ConcreteHandler2();

handler1.setNext(handler2);

console.log(handler1.handle('Request1')); // Output: ConcreteHandler1 handling Request1
console.log(handler1.handle('Request2')); // Output: ConcreteHandler2 handling Request2
console.log(handler1.handle('Request3')); // Output: null

In this example, the Handler class represents the base handler interface, and ConcreteHandler1 and ConcreteHandler2 are concrete handlers that extend the base handler. The client code sets up a chain of handlers and sends requests to the first handler in the chain.

Live Playground, Try it Yourself

Benefits of the Chain of Responsibility Pattern

Implementing the Chain of Responsibility pattern in your JavaScript projects offers several benefits:

  1. Loose Coupling: The Chain of Responsibility pattern promotes loose coupling by decoupling the sender of a request from its receiver, allowing multiple objects to handle the request without needing to know the specifics of each handler.
  2. Dynamic Handling: The Chain of Responsibility pattern enables dynamic handling of requests, with each handler deciding whether to process the request or pass it along, making it easy to add, remove, or modify handlers without affecting the overall system.
  3. Maintainability and Scalability: The Chain of Responsibility pattern improves code maintainability and scalability by promoting separation of concerns and allowing you to easily add or remove handlers in the chain.

Conclusion

In summary, the Chain of Responsibility pattern is a valuable tool in JavaScript development that can help you create maintainable, scalable code. By understanding and implementing this pattern, you can enhance your web development skills and create more robust applications.