On this page
13. Chain of Responsibility
The Chain of Responsibility pattern is a behavioral design pattern that allows a request to be passed along a chain of handlers. Each handler in the chain can either process the request or pass it along to the next handler. This pattern decouples the sender of a request from the receiver by allowing multiple objects to handle the request without knowing which object will handle it.
Key Characteristics:
- Decoupling: The sender of the request does not need to know which handler will process it.
- Chain of Handlers: Allows multiple handlers to process the request in sequence.
- Responsibility Passing: Each handler decides whether to process the request or pass it along the chain.
How It Works:
- Handler Interface: Defines an interface for handling requests and provides a method to set the next handler in the chain.
- Concrete Handlers: Implement the handler interface and define the logic for processing the request or passing it to the next handler.
- Client: Creates and configures the chain of handlers and initiates the request.
Example in PHP:
// Handler Interface
interface Handler {
public function setNext(Handler $handler);
public function handleRequest($request);
}
// Concrete Handler A
class ConcreteHandlerA implements Handler {
private $nextHandler;
public function setNext(Handler $handler) {
$this->nextHandler = $handler;
}
public function handleRequest($request) {
if ($request == 'A') {
echo "Handler A processing request.\n";
} elseif ($this->nextHandler !== null) {
$this->nextHandler->handleRequest($request);
}
}
}
// Concrete Handler B
class ConcreteHandlerB implements Handler {
private $nextHandler;
public function setNext(Handler $handler) {
$this->nextHandler = $handler;
}
public function handleRequest($request) {
if ($request == 'B') {
echo "Handler B processing request.\n";
} elseif ($this->nextHandler !== null) {
$this->nextHandler->handleRequest($request);
}
}
}
// Concrete Handler C
class ConcreteHandlerC implements Handler {
private $nextHandler;
public function setNext(Handler $handler) {
$this->nextHandler = $handler;
}
public function handleRequest($request) {
if ($request == 'C') {
echo "Handler C processing request.\n";
} elseif ($this->nextHandler !== null) {
$this->nextHandler->handleRequest($request);
}
}
}
// Client Code
$handlerA = new ConcreteHandlerA();
$handlerB = new ConcreteHandlerB();
$handlerC = new ConcreteHandlerC();
$handlerA->setNext($handlerB);
$handlerB->setNext($handlerC);
$handlerA->handleRequest('B'); // Output: Handler B processing request.
$handlerA->handleRequest('C'); // Output: Handler C processing request.
$handlerA->handleRequest('A'); // Output: Handler A processing request.
$handlerA->handleRequest('X'); // No output, request not handled.
Explanation:
- Handler Interface: Handler defines methods for setting the next handler in the chain and handling requests.
- Concrete Handlers: ConcreteHandlerA, ConcreteHandlerB, and ConcreteHandlerC implement the Handler interface. Each concrete handler decides whether it can process the request or pass it along to the next handler in the chain.
- Client Code: Configures the chain of handlers and sends requests. Each request is processed by the appropriate handler or passed along the chain if not handled by the current handler.
Benefits:
- Flexibility: Allows adding new handlers or changing the order of handlers without modifying existing code.
- Decoupling: Separates request handling from the request sender and receiver.
- Dynamic Handling: Requests can be handled by different handlers based on their type or content.
se Cases:
- Event Handling: In systems where events need to be processed by multiple handlers in sequence.
- Logging and Validation: When multiple steps are needed for logging, validation, or processing before an action is completed.
The Chain of Responsibility pattern provides a flexible way to handle requests through a chain of handlers, making it easier to manage complex processing sequences and improve code maintainability.