1 Chain of Responsibility (Behavioral) Design Pattern

The Chain of Responsibility Pattern is a behavioral design pattern that allows a request to be passed along a chain of handlers until one of them handles it. This pattern promotes loose coupling by letting the sender of a request and the receivers (handlers) interact indirectly.

The Chain of Responsibility is a behavioral design pattern that allows a request to be passed sequentially through a chain of handlers. Each handler determines whether to process the request or forward it to the next handler in the sequence.

Problem

Imagine you're building an online ordering system that needs robust access control. To ensure security and proper functionality, the system must enforce several sequential checks:

  1. Authentication: Only authenticated users can create orders.
  2. Authorization: Users with administrative permissions have full access to manage all orders.

At first, these checks seemed manageable. The application would attempt to authenticate users based on credentials in the incoming request. If authentication failed, no further checks were performed.

Growing Complexity Over Time:

As the system evolved, new requirements arose:

  • Data Validation: A colleague pointed out the risk of processing raw request data, so you added a step to sanitize inputs.
  • Brute Force Protection: To defend against password cracking attempts, you implemented a check to block repeated failed requests from the same IP address.
  • Caching: To improve performance, you added a mechanism to return cached results for repeated requests with identical data, bypassing other checks when possible.

Each new feature added more complexity. The code for these checks, initially simple, turned into a tangled mess. Adding or modifying a check often broke unrelated parts of the system. Reusing these checks for other components became a nightmare since those components required only specific checks, forcing you to duplicate code.

Solution:

The Chain of Responsibility pattern offers an elegant solution to problems involving sequential checks or processes. It works by encapsulating specific behaviors into separate, self-contained objects called handlers. Each handler is responsible for performing one type of check or operation.

In the context of an online ordering system, each security or performance check—such as authentication, authorization, data validation, brute-force protection, or caching—would be implemented as a standalone class with a single method to handle requests. The request, along with its associated data, is passed to this method for processing.

The pattern then connects these handlers into a chain, where:

  1. Each handler contains a reference to the next handler in the chain.
  2. When a handler finishes its check, it decides whether to pass the request to the next handler.
  3. The request flows through the chain until either all handlers have processed it, or one handler stops the chain.

First-Responder Style

A slightly different and more canonical approach focuses on single responsibility:

  • When a handler receives a request, it determines if it can process it.
  • If it can, it handles the request and stops further propagation.
  • If it cannot, the request is passed to the next handler.

This style ensures that only one handler processes the request, which is particularly useful for event-driven systems.

Real-World Analogy: GUI Event Handling

Consider a graphical user interface (GUI) where user actions (like clicking a button) generate events:

  1. The event flows through a chain of GUI elements, starting with the button and propagating through its containers (like panels or windows).
  2. The first element capable of handling the event processes it, and the propagation stops.
  3. This chain is often derived from the hierarchical structure of GUI components, showing that a chain can be extracted from an object tree.

References