Chain of Responsibility Pattern

The Chain of Responsibility is a behavioral design pattern that allows a request to be passed along a chain of handlers, where each handler decides to process it or pass to the next. It decouples the sender from receivers, enabling dynamic handler ordering and avoiding if-else cascades.

Key Principles

Structure

Python Example: Logging Middleware Chain

from abc import ABC, abstractmethod

# Handler Abstract Class
class Logger(ABC):
    def __init__(self):
        self._next = None

    def set_next(self, handler) -> 'Logger':
        self._next = handler
        return handler

    @abstractmethod
    def handle_log(self, level: str, message: str):
        pass

    def _handle_next(self, level: str, message: str):
        if self._next:
            return self._next.handle_log(level, message)
        print(f"[Unlogged] {level}: {message}")

# Concrete Handlers
class ErrorLogger(Logger):
    def handle_log(self, level: str, message: str):
        if level == "ERROR":
            print(f"ERROR: {message}")
            return
        self._handle_next(level, message)

class WarningLogger(Logger):
    def handle_log(self, level: str, message: str):
        if level == "WARNING":
            print(f"WARNING: {message}")
            return
        self._handle_next(level, message)

class InfoLogger(Logger):
    def handle_log(self, level: str, message: str):
        if level == "INFO":
            print(f"INFO: {message}")
            return
        self._handle_next(level, message)

# Usage (Client Code)
if __name__ == "__main__":
    # Build chain: Error → Warning → Info
    error = ErrorLogger()
    warning = WarningLogger()
    info = InfoLogger()

    chain = error.set_next(warning).set_next(info)

    # Test requests
    chain.handle_log("ERROR", "Disk full")
    chain.handle_log("WARNING", "High CPU usage")
    chain.handle_log("INFO", "User logged in")
    chain.handle_log("DEBUG", "Minor event")  # Falls through

Output:

ERROR: Disk full
WARNING: High CPU usage
INFO: User logged in
[Unlogged] DEBUG: Minor event

When to Use Chain of Responsibility

Summary: Chain of Responsibility links handlers in a sequence, passing requests until one processes it, promoting flexibility and decoupling.