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:

  1. Handler Interface: Handler defines methods for setting the next handler in the chain and handling requests.
  2. 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.
  3. 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.