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 ---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