Chain of Responsibility Method Design Pattern in Javascript
Last Updated :
26 Aug, 2024
The Chain of Responsibility design pattern in JavaScript allows a request to be passed through a chain of handlers until one processes it. This pattern helps manage complex workflows by decoupling the sender of a request from its receivers, making the system more flexible and easier to extend. In this article, we'll explore how to implement the Chain of Responsibility in JavaScript, with practical examples to demonstrate its use in creating more maintainable and scalable code.
Chain of Responsibility Method Design Pattern in JavascriptImportant Topics for Chain of Responsibility Method Design Pattern in Javascript
What is the Chain of Responsibility Method Design Pattern?
The Chain of Responsibility method design pattern is a behavioral pattern that allows multiple objects to handle a request, passing it along a chain until one of the objects handles it. Each object in the chain either processes the request or passes it to the next handler in the chain. This pattern is useful for decoupling the sender of a request from its receivers, providing a way to handle requests by different handlers without hard-wiring the request-processing code to specific classes. It promotes flexibility in assigning responsibilities to objects dynamically.
Components of Chain of Responsibility Method Design Pattern
The Chain of Responsibility design pattern consists of several key components:
- Handler Interface: Defines an interface for handling requests. It typically includes a method to handle the request and a method to set the next handler in the chain.
- Concrete Handler: Implements the handler interface and processes the request. If the handler cannot process the request, it passes it to the next handler in the chain.
- Client: Initiates the request and sets up the chain of handlers. The client sends the request to the first handler in the chain.
- Next Handler Reference: A reference in each handler to the next handler in the chain, allowing the request to be passed along the chain if the current handler cannot process it.
Chain of Responsibility Method Design Pattern Example in Javascript
Problem Statement:
Imagine a tech support system where customer queries are handled by different levels of support agents. A basic query can be handled by a Level 1 support agent, but more complex issues need to be escalated to Level 2 or even Level 3 support. Without a clear process, queries might be mishandled, leading to delays or unresolved issues. The challenge is to efficiently route each customer query to the appropriate support level.
How does the Chain of Responsibility Method Design Pattern solve this problem?
The Chain of Responsibility design pattern can be applied to solve this problem. Each support level will be a handler in the chain, processing the query or passing it on to the next level if it cannot handle it.
Below is the implementation of the above approach:
Class Diagram of Chain of Responsibility Method Design Pattern1. Handler Interface
JavaScript
class SupportHandler {
setNextHandler(handler) {
this.nextHandler = handler;
}
handleRequest(query) {
throw new Error("This method should be overridden!");
}
}
2. Concrete Handlers (Level 1, Level 2, and Level 3 Support)
JavaScript
class Level1Support extends SupportHandler {
handleRequest(query) {
if (query.difficulty === "easy") {
console.log("Level 1 Support: Handling easy query.");
} else if (this.nextHandler) {
this.nextHandler.handleRequest(query);
}
}
}
class Level2Support extends SupportHandler {
handleRequest(query) {
if (query.difficulty === "medium") {
console.log("Level 2 Support: Handling medium query.");
} else if (this.nextHandler) {
this.nextHandler.handleRequest(query);
}
}
}
class Level3Support extends SupportHandler {
handleRequest(query) {
if (query.difficulty === "hard") {
console.log("Level 3 Support: Handling hard query.");
} else if (this.nextHandler) {
this.nextHandler.handleRequest(query);
} else {
console.log("Query cannot be handled at any level.");
}
}
}
3. Client Setup
JavaScript
// Creating support levels
const level1 = new Level1Support();
const level2 = new Level2Support();
const level3 = new Level3Support();
// Setting up the chain
level1.setNextHandler(level2);
level2.setNextHandler(level3);
// Example queries
const easyQuery = { difficulty: "easy" };
const mediumQuery = { difficulty: "medium" };
const hardQuery = { difficulty: "hard" };
const unknownQuery = { difficulty: "unknown" };
// Handling the queries
level1.handleRequest(easyQuery);
level1.handleRequest(mediumQuery);
level1.handleRequest(hardQuery);
level1.handleRequest(unknownQuery);
Below is the complete code provided:
JavaScript
// Handler Interface
class SupportHandler {
setNextHandler(handler) {
this.nextHandler = handler;
}
handleRequest(query) {
throw new Error("This method should be overridden!");
}
}
// Concrete Handlers
class Level1Support extends SupportHandler {
handleRequest(query) {
if (query.difficulty === "easy") {
console.log("Level 1 Support: Handling easy query.");
} else if (this.nextHandler) {
this.nextHandler.handleRequest(query);
}
}
}
class Level2Support extends SupportHandler {
handleRequest(query) {
if (query.difficulty === "medium") {
console.log("Level 2 Support: Handling medium query.");
} else if (this.nextHandler) {
this.nextHandler.handleRequest(query);
}
}
}
class Level3Support extends SupportHandler {
handleRequest(query) {
if (query.difficulty === "hard") {
console.log("Level 3 Support: Handling hard query.");
} else if (this.nextHandler) {
this.nextHandler.handleRequest(query);
} else {
console.log("Query cannot be handled at any level.");
}
}
}
// Client Code
const level1 = new Level1Support();
const level2 = new Level2Support();
const level3 = new Level3Support();
level1.setNextHandler(level2);
level2.setNextHandler(level3);
const easyQuery = { difficulty: "easy" };
const mediumQuery = { difficulty: "medium" };
const hardQuery = { difficulty: "hard" };
const unknownQuery = { difficulty: "unknown" };
level1.handleRequest(easyQuery);
level1.handleRequest(mediumQuery);
level1.handleRequest(hardQuery);
level1.handleRequest(unknownQuery);
OutputLevel 1 Support: Handling easy query.
Level 2 Support: Handling medium query.
Level 3 Support: Handling hard query.
Query cannot be handled at any level.
Below is the explanation of the above code:
- SupportHandler: This is the base class with methods to set the next handler and handle requests.
- Level1Support, Level2Support, Level3Support: These are concrete handlers. Each one checks if it can handle the query. If not, it passes the query to the next handler in the chain.
- Client Setup: The client sets up the chain of responsibility by linking the support levels. When a query is passed to the first handler, it either processes it or passes it along the chain.
This design pattern is effective in handling queries of varying complexity by delegating responsibility through a chain, ensuring each query reaches the appropriate handler.
When to Use the Chain of Responsibility Design Pattern
- When multiple objects can handle a request and the handler is determined at runtime.
- When you want to decouple the sender and receiver of a request.
- When you want to simplify the code by allowing request processing to be passed through a chain of handlers.
When Not to Use the Chain of Responsibility Design Pattern
- When a single handler should always handle a request.
- When the request processing should not be passed to multiple handlers.
- When performance is a concern, as passing requests through a chain can introduce overhead.
By implementing the Chain of Responsibility pattern, you can create flexible and decoupled systems where requests are handled by different handlers based on their type or context. This pattern is especially useful in scenarios where you have a series of processing steps that can be organized into a pipeline of handlers.
Similar Reads
Chain of Responsibility Design Pattern in Java
The Chain of Responsibility Design Pattern in Java is a behavioral design pattern that allows an object to pass a request along a chain of handlers. Each handler in the chain decides either to process the request or to pass it along the chain to the next handler. Important Topics for Chain of Respon
9 min read
Chain of Responsibility Design Pattern
The Chain of Responsibility design pattern is a behavioral design pattern that allows an object to pass a request along a chain of handlers. Each handler in the chain decides either to process the request or to pass it along the chain to the next handler. Table of Content What is the Chain of Respon
10 min read
Proxy Method Design Pattern in Javascript
The Proxy Method Design Pattern in JavaScript involves creating a proxy object that controls access to another object, allowing you to define custom behavior for operations like property access and method calls. This pattern is useful for adding features such as logging, validation, and access contr
8 min read
Singleton Method Design Pattern in JavaScript
Singleton Method or Singleton Design Pattern is a part of the Gang of Four design pattern and it is categorized under creational design patterns. It is one of the most simple design patterns in terms of modeling but on the other hand, this is one of the most controversial patterns in terms of comple
10 min read
Command Method | JavaScript Design Patterns
The command method is a behavioral design pattern that encapsulates an incoming request into a standalone object. This object contains all the necessary information to perform a request including the method to call and parameters. Important Topics for the Command Method in JavaScript Design Patterns
6 min read
Prototype Method - JavaScript Design Pattern
A Prototype Method is a JavaScript design pattern where objects share a common prototype object, which contains shared methods. The prototype method allows you to reuse the properties and methods of the prototype object, and also add new ones as needed. The prototype method is useful for performance
3 min read
Template Method | JavaScript Design Patterns
Template Method is a behavioral design pattern that defines the skeleton of an algorithm in a base class while allowing subclasses to implement specific steps of the algorithm without changing its structure. It promotes code reusability and provides a way to enforce a consistent algorithm structure
10 min read
Chain of Responsibility - Python Design Patterns
Chain of Responsibility method is Behavioral design pattern and it is the object-oriented version of if ... elif ... elif ... else and make us capable to rearrange the condition-action blocks dynamically at the run-time. It allows us to pass the requests along the chain of handlers. The processing i
4 min read
Mediator Design Pattern in JavaScript | Design Pattern
The Mediator pattern is a behavioral design pattern that promotes loose coupling between objects by centralizing communication between them. It's particularly useful when you have a complex system with multiple objects that need to interact and you want to avoid the tight coupling that can arise fro
5 min read
Bridge Method | JavaScript Design Pattern
In software design, as systems grow and evolve, the complexity of their components can increase exponentially. This complexity often arises from the intertwining of different functionalities and features, making the system rigid, less maintainable, and harder to scale. The Bridge design pattern emer
9 min read