A Beginner’s Guide To Building Flexible Code With the Chain of Responsibility Design Pattern in JavaScript

author

Padmaram G

November 14, 2023

Last updated: August 16, 2024

chain of responsibility design pattern

When developing software, you may encounter situations where specific tasks need to be performed, but you’re uncertain about who will carry out these tasks. In such cases, the JavaScript Chain of Responsibility design pattern comes to the rescue. This behavioral pattern enables request clients to submit their requests without needing to know how these requests will be ultimately processed. 

In essence, it allows an object to dispatch commands to other objects without prior knowledge of which object will handle the request upon receiving it. Think of it as a leader delegating tasks, where the leader’s sole responsibility is task assignment, and they remain unaware of who exactly will execute these tasks. This approach promotes efficient task distribution and execution throughout the system.

What Is the Chain Of Responsibility Pattern?

The Chain of Responsibility design pattern, a part of the behavioral design pattern, is a powerful mechanism for handling requests in a way that abstracts the requestor from the specifics of how and by whom the request will be fulfilled. It fosters a more flexible and modular system by enabling tasks to be efficiently divided and executed without the need for requesters to know the precise details of their handling.

How Does The Chain Of Responsibility Pattern Work?

In the Chain of Responsibility pattern, each handler in the chain has the ability to either handle the request or pass it along to the next handler. This approach effectively decouples the sender of the request from its potential recipients, enabling multiple objects to participate in processing the request without creating complex interdependencies.

In this pattern, there are three key components:

  • The sender
  • The recipient
  • The request 

The sender is responsible for initiating requests, while the recipient is composed of a series of one or more objects. Each of these objects has the authority to decide whether to directly respond to the request or delegate it to the next object in the chain. The request can take the form of a standard function call to the recipient without any parameters, or it can be encapsulated within an object containing all the necessary data.

The initial receiver object at the beginning of the chain is where senders dispatch their requests. Senders are only aware of this first link in the chain and have no knowledge of subsequent receivers. The primary receiver can choose to handle the request or pass it on to a secondary receiver in the chain for further processing.

In essence, the Chain of Responsibility pattern offers a flexible and modular way to handle requests in a way that promotes code reusability and maintains a clear separation of concerns.

A Real Life Example

In the real world, the JavaScript Chain of Responsibility design pattern can be illustrated through the operation of an ATM (Automated Teller Machine). When we insert our ATM card into the machine and initiate a transaction, the ATM system employs the Chain of Responsibility pattern to handle our request, ultimately providing us with the requested cash.

Chain of Responsibility Pattern in JavaScript

Practical Applications Of Chain Of Responsibility Design Pattern In JavaScript

1. Event Propagation: The Chain of Responsibility pattern finds practical use in the space of user interface frameworks. It enables the seamless propagation of events throughout nested UI components. This empowers various elements to react to these events at different hierarchical levels, ensuring a flexible and extensible approach to event handling.

2. Logging Strategies: This design pattern is a valuable asset in the space of logging systems. It’s adept at forming a chain of responsibility for handling distinct log levels and message types. Loggers can be structured in a way that allows each logger in the chain to process logs according to its specific criteria, providing a sophisticated and customizable logging strategy.

3. Middleware Management: Web frameworks, such as Express.js, make effective use of the Chain of Responsibility pattern to manage middleware. In this context, middleware components are organized in a chain, where each middleware can either process incoming requests or pass them along to the next middleware in line. This approach ensures efficient request handling and allows for the creation of complex request-processing pipelines.

Are you excited about the prospect of creating a tailor-made web application from the ground up, modernizing your outdated backend infrastructure, or optimizing and enhancing your current front-end functionalities? Calibraint, a specialized web application development company can make your vision a reality!

Let us now understand the Chain of Responsibility pattern in JavaScript with a code example.

Example Code:

In a web application, the Chain of Responsibility design pattern in JavaScript can be illustrated through the process of handling incoming HTTP requests. Let’s consider a real-world scenario:

Imagine you’re developing a web application that receives incoming HTTP requests, and these requests need to pass through several processing stages before generating a response. These processing stages include authentication, authorization, input validation, and response formatting. Each of these stages is managed by a separate component, and they are organized in a chain.

In this scenario, the Chain of Responsibility design pattern is a design approach that allows each processing step to be treated as a separate handler. The request is passed through this chain of handlers, and each handler has the option to process the request or pass it on to the next handler in the chain. This provides flexibility and modularity, making it easier to add or remove processing steps without affecting the overall request processing flow.

Let us see the steps in detail! 

Step 1: Create A Request

Creating a request in chain of responsibility pattern
  • In the above code, the Request class is a blueprint for creating objects that represent HTTP requests in a web application.
  • It has a constructor function that takes three parameters: method, path, and data. These parameters represent the HTTP method (e.g., GET, POST), the request path (e.g., “/login”), and any data associated with the request (e.g., user credentials).
  •  After defining the Request class, create a new instance of the ‘Request’ class.

Step 2: Define The Handlers

Defining the handlers in chain of responsibility pattern
  • Handler is the base class that serves as the foundation for all handlers in the chain.
  • It has a constructor that can optionally accept a successor handler. This successor will be the next handler in the chain.
  • The handleRequest method is used to handle a request. If the handler has a successor (i.e., the successor property is set), it delegates the request to the successor. Otherwise, it does not do anything.
  • HandlerA, HandlerB, and HandlerC Classes handle classes that inherit from the Handler base class.
  • Each handler implements its own handleRequest method to perform specific tasks based on the request it receives.
  • In each handleRequest method, it checks whether it can handle the request based on certain conditions (e.g., request method and path).
  • If the conditions match, the handler performs its specific task (e.g., authentication, authorization, input validation) and logs a message indicating that it’s handling the request.
  • If the conditions do not match, the handler calls ‘super.handleRequest(request)’ to pass the request to the next handler in the chain (if it exists).

Step 3 : Creating A Main Function

creating a main function in chain of responsibility pattern
  • The ‘main’ function builds a chain of handlers and processes a request through that chain to show how the Chain of Responsibility pattern operates. Hierarchically and flexibly, each handler has an opportunity to handle the request or pass it on to the next handler. The sequence in which they try to process the request is determined by the ordering of handlers in the chain.
  • A chain of responsibility is then constructed(handlerChain). It creates instances of three handler classes: HandlerC, HandlerB, and HandlerA.
  • The order of construction matters because it determines the sequence in which the handlers will attempt to handle a request. In this case, HandlerC is the first handler in the chain, followed by HandlerB, and finally HandlerA.
  • It then creates an instance of the request object representing an HTTP POST request (‘requests’).
  • The ‘handleRequest’ method of the first handler in the chain (HandlerC) is called with the ‘requests’ object as an argument.
  • The request is then processed sequentially through the chain of responsibility.

Benefits and Advantages Of Chain Of Responsibility Pattern In JavaScript

Benefits Of Chain Of Responsibility Pattern In JavaScript
  1. Reduced Dependency: The Chain of Responsibility pattern promotes a reduction in intricate dependencies, allowing both senders and receivers to remain flexible. This, in turn, enhances system flexibility and simplifies maintenance tasks.
  2. Single Responsibility Principle: Each handler strictly adheres to the Single Responsibility Principle, focusing exclusively on its designated task. This ensures that a class serves a singular purpose, making it easier to manage and modify.
  3. Dynamic Flexibility: The chain’s structure can be dynamically adjusted, enabling the seamless addition or rearrangement of handlers without the need to modify existing code. This adaptability simplifies system maintenance and evolution.
  4. Managing Complex Execution Paths: In complex systems with numerous interacting components, this pattern offers an elegant solution for navigating dynamic and conditional execution paths, enhancing code organization and maintainability.

End Lines

The Chain of Responsibility pattern is a powerful design pattern that promotes scalability, flexibility, and maintainability in software systems. It allows a request to traverse through a chain of handlers until it is successfully processed or determined to be outside the scope of the system, depending on each handler’s logic within the chain that you can design.

By separating sender and receiver objects, this pattern simplifies the process of modifying and expanding the system without affecting other parts of the code. It is especially useful in scenarios where numerous objects need to respond to requests in a hierarchical or sequential manner, such as in authentication, authorization, validation, or event processing. Thus, developers can seamlessly create flexible systems by leveraging the Chain of Responsibility pattern. 

Article By,
Padmaram G (SDE I)

Related Articles

field image

Ever Coded Yourself into a Corner with Multiple Instances? Imagine you’re building a complex JavaScript application. You need a single point of control for something crucial, like a configuration manager or a user session. You create a class, but then… disaster strikes! Your code accidentally creates multiple instances, wreaking havoc on your carefully crafted logic. […]

author-image

Calibraint

Author

02 May 2024

field image

Ever felt lost in a jungle of constructors? JavaScript doesn’t explicitly require them for object creation, but sometimes managing them can become cumbersome. The Factory Design Pattern in JavaScript offers a solution! This blog will be your guide through this creational design pattern, explaining how it centralizes object creation logic and enhances code flexibility. We’ll […]

author-image

Calibraint

Author

08 Apr 2024

field image

An Introduction To Observer Design Pattern In JavaScript Ever felt like your JavaScript code is a tangled mess of event listeners and callbacks, each desperately trying to react to changes in various parts of your application? Worry not, fellow developers! There’s a design pattern that can help you with this confusion: the Observer Design Pattern […]

author-image

Haritha N

04 Mar 2024

field image

A Preface To Dynamic Prototype Pattern in JavaScript The Dynamic Prototype Pattern in JavaScript introduces a versatile and powerful approach to object creation, offering a flexible mechanism for enhancing objects with new properties and methods dynamically.  A Brief Summary Of Dynamic Prototype Patterns In JavaScript The Dynamic Prototype Pattern falls within the group of creational […]

author-image

Calibraint

Author

01 Feb 2024

field image

Mastering design patterns in JavaScript is crucial for crafting robust and maintainable code. One such pattern that stands out for its versatility and impact on code architecture is the Proxy Design Pattern in JavaScript.  Whether you’re aiming to optimize performance, enhance security, or simply gain a deeper understanding of JavaScript’s capabilities, this exploration of the […]

author-image

Vishnu Prasath

05 Jan 2024

field image

At times, we encounter situations that require the construction of intricate objects involving the execution of multiple sequential operations. In such cases, the builder design pattern in JavaScript emerges as a valuable solution. The JavaScript builder pattern falls within the category of Creational Design Patterns in JavaScript. Its introduction aimed to address certain challenges associated […]

author-image

Haritha N

28 Dec 2023

Let's Start A Conversation

Table of Contents