Chain of Responsibility#

The Chain of Responsibility is a behavioral design pattern that allows an object to pass the request along the chain of potential handlers until an object handles it. It involves a source of command objects and a series of processing objects. Each processing object contains a logic that defines the types of command objects that it can handle, and how to pass off those it can’t to the next processing object in the chain.

--- UML diagram ---
 +-------------------+        +-------------------+
 |    Handler        |<-------|  ConcreteHandler1 |
 |-------------------|        |-------------------|
 | +set_next()       |        | +set_next()       |
 | +handle(request)  |        | +handle(request)  |
 +-------------------+        +-------------------+
         ^                           ^
         |                           |
 +-------------------+        +-------------------+
 |  ConcreteHandler2 |        |  ConcreteHandler3 |
 |-------------------|        |-------------------|
 | +set_next()       |        | +set_next()       |
 | +handle(request)  |        | +handle(request)  |
 +-------------------+        +-------------------+

In this diagram, Handler is an interface with methods set_next() and handle(request). ConcreteHandler1, ConcreteHandler2, and ConcreteHandler3 are classes that implement the Handler interface. The arrows indicate that the ConcreteHandler classes inherit from the Handler interface.

Java Example#

public interface Handler {
    void setNext(Handler handler);
    void handle(String request);
}

public class ConcreteHandler1 implements Handler {
    private Handler next;

    @Override
    public void setNext(Handler handler) {
        this.next = handler;
    }

    @Override
    public void handle(String request) {
        if ("request1".equals(request)) {
            System.out.println("ConcreteHandler1 handled the request1");
        } else if (next != null) {
            next.handle(request);
        }
    }
}

public class ConcreteHandler2 implements Handler {
    private Handler next;

    @Override
    public void setNext(Handler handler) {
        this.next = handler;
    }

    @Override
    public void handle(String request) {
        if ("request2".equals(request)) {
            System.out.println("ConcreteHandler2 handled the request2");
        } else if (next != null) {
            next.handle(request);
        }
    }
}

Python Example#

from __future__ import annotations
from abc import ABC, abstractmethod

class Handler(ABC):
    @abstractmethod
    def set_next(self, handler: Handler) -> Handler:
        pass

    @abstractmethod
    def handle(self, request: str) -> str:
        pass

class ConcreteHandler1(Handler):
    _next_handler: Handler = None

    def set_next(self, handler: Handler) -> Handler:
        self._next_handler = handler
        return handler

    def handle(self, request: str) -> str:
        if request == "request1":
            return f"ConcreteHandler1: Handled {request}"
        elif self._next_handler:
            return self._next_handler.handle(request)
        return None

class ConcreteHandler2(Handler):
    _next_handler: Handler = None

    def set_next(self, handler: Handler) -> Handler:
        self._next_handler = handler
        return handler

    def handle(self, request: str) -> str:
        if request == "request2":
            return f"ConcreteHandler2: Handled {request}"
        elif self._next_handler:
            return self._next_handler.handle(request)
        return None