The Chain of Responsibility Design Pattern

The Chain of Responsibility pattern decouples sender and receiver by giving more than one object a chance to handle a request.

Use the Chain of Responsibility pattern when you want to pass a request along a chain of handlers and allow any of them to process the request.

  • TypeBehavioral
  • Time ComplexityO(n) Linear Time – The time taken grows linearly with the size of the input. Examples include simple search algorithms.
  • Efficiency6
  • Learning Effort

    • Average6
    • Conceptual6
    • Debug and Maintain6
    • Implementation5
    • Prerequisites4
    • Versatility7

Things you should know before you start

  • Recursion Understanding of recursion, as the request is passed along a chain in a recursive manner.
  • Loose Coupling Understanding of loose coupling, as the pattern aims to decouple the sender and receiver.

Minimal Example

Implementing a logging system where messages can be logged to different channels like console, file, or database.

class Logger {
  setNext(logger: Logger): void {}
  log(message: string): void {}
}
const consoleLogger = new ConsoleLogger();
const fileLogger = new FileLogger();
consoleLogger.setNext(fileLogger);
consoleLogger.log('This is a message');

What’s happening in thie example

In this example, the `Logger` class serves as the Handler. The `clientCode` shows how loggers are chained and how a message is passed along the chain.

How the Chain of Responsibility Works

The Chain of Responsibility pattern allows multiple objects to handle a request without coupling the sender class to the classes of the concrete handlers.

This pattern simplifies object interactions by allowing objects to pass the request along a chain until an object handles it.

Entities in the Chain of Responsibility Design Pattern

  • HandlerThe Handler interface defines a method for handling requests. It also optionally defines a successor to pass the request to.

    • Handler has a one-to-many inherits relationship with ConcreteHandler

What to watch out for when using or considering this design pattern.

Avoid using the Chain of Responsibility pattern when each request is only handled by one handler, or when the client object knows which service object should handle the request.

Design patterns often confused with the Chain of Responsibility Design Pattern

The following design patterns are often confused with the Chain of Responsibility
for various resons.

If you’re exploring solutions, have a look through this list and see if
one of these might be a better fit for your problem.

  • Observer – The Observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified.

    The Observer pattern is similar to the Chain of Responsibility in the following ways.

    • Both are behavioral design patterns.
    • Both deal with object communication.
  • Here are some notable differences with the Chain of Responsibility pattern.

    • Chain of Responsibility passes the request along a chain, whereas Observer distributes state changes to all registered observers.
    • In Chain of Responsibility, each handler decides whether to pass the request along the chain; in Observer, all observers are notified.
  • Command – The Command pattern encapsulates a request as an object, thereby allowing for parameterization of clients with different requests.

    The Command pattern is similar to the Chain of Responsibility in the following ways.

    • Both are behavioral design patterns.
    • Both deal with encapsulating requests.
  • Here are some notable differences with the Chain of Responsibility pattern.

    • Chain of Responsibility focuses on handling requests by passing them along a chain, while Command focuses on encapsulating a request as an object.
    • In Chain of Responsibility, handlers are linked, whereas in Command, there is no inherent linking of command objects.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top